<commit_before>import Ember from 'ember';

export function ratings(params /*, hash*/ ) {
  // var rati = params[0].get('ratings');

  var ratings = params[0].get('ratings').map(function(rating) {
    return rating.get('rating');
  });
  var total = 0
  for (var i = 0; i < ratings.length; i++) {
    total = ratings[i] + total
  }
  var av = total / ratings.length
  return av.toFixed(1)
  // if (rentalPrice >= 150) {
  //   return '$$$$';
  // } else if (rentalPrice >= 100) {
  //   return '$$$';
  // } else if (rentalPrice >= 50) {
  //   return '$$';
  // } else if (rentalPrice <= 49) {
  //   return '$';
  // }
}

export default Ember.Helper.helper(ratings);
<commit_msg>fix the average rating for 0<commit_after>import Ember from 'ember';

export function ratings(params /*, hash*/ ) {
  // var rati = params[0].get('ratings');

  var ratings = params[0].get('ratings').map(function(rating) {
    return rating.get('rating');
  });
  var total = 0
  for (var i = 0; i < ratings.length; i++) {
    total = ratings[i] + total
  }
  var av = total / ratings.length
  var st = av.toString()
  console.log(st);
  if (st === 'NaN') {

    return 0
  } else {
    return av.toFixed(1)
  }

}

export default Ember.Helper.helper(ratings);
<|endoftext|>


<commit_before>// Import the page's CSS. Webpack will know what to do with it.
import "../stylesheets/app.css";

// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'

import crowdfund_artifacts from '../../build/contracts/Crowdfund.json'

var crowdfund = contract(crowdfund_artifacts);

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
var accounts;
var account;

window.App = {
  start: function() {
    var self = this;

  },

};

window.addEventListener('load', function() {
  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {
    console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  App.start();
});
<commit_msg>playing with node app<commit_after>// Import the page's CSS. Webpack will know what to do with it.
import "../stylesheets/app.css";

// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'

import crowdfund_artifacts from '../../build/contracts/Crowdfund.json'

var Crowdfund = contract(crowdfund_artifacts);

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
var accounts;
var account;

window.App = {
  start: function() {
    var self = this;

    Crowdfund.setProvider(web3.currentProvider);

  },

};

window.addEventListener('load', function() {
  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {
    console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  App.start();
});
<|endoftext|>


<commit_before>
define([
  'jquery',
  'underscore',
  'backbone',
  'helpers/usertag'
], function ($, _, Backbone, UserTagHelper) {

  var Entry = Backbone.Model.extend ({

    defaults: {
      content: '',
      rawContent: '',
      creationTime: '',
      modifyTime: '',
      author: '',
      isFavorite: false,
      favoriteCount: 0,
    },

    relativeTime: function (time) {
      var current = new Date ();

      var msPerMinute = 60 * 1000;
      var msPerHour = msPerMinute * 60;
      var msPerDay = msPerHour * 24;
      var msPerMonth = msPerDay * 30;
      var msPerYear = msPerDay * 365;

      // FIXME: need to check DST
      var elapsed = current - new Date (time) + (3*60*60*1000);

      if (elapsed < msPerMinute) {
        return Math.round (elapsed/1000) + ' saniye';
      }

      else if (elapsed < msPerHour) {
        return Math.round (elapsed/msPerMinute) + ' dakika';
      }

      else if (elapsed < msPerDay ) {
        return Math.round (elapsed/msPerHour ) + ' saat';
      }

      else if (elapsed < msPerMonth) {
        return Math.round (elapsed/msPerDay) + ' gün';
      }

      else if (elapsed < msPerYear) {
        return Math.round (elapsed/msPerMonth) + ' ay';
      }

      else {
        return Math.round (elapsed/msPerYear ) + ' yıl';
      }
    },

    parseContent: function (content) {

      var that = this;

      var contentObj = $.parseHTML ('
' + content + '
');

      $(contentObj).find ('a').each (function () {

        // EXTERNAL LINKS
        if ($(this).attr ('href').match (/^https?\:\/\//)) {

          var matches = $(this).attr ('href')
                               .match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
          var domain = matches && matches[1];
          domain = domain.replace (/^[^.]*\.(?=\w+\.\w+$)/, '');

          // show picture glyphicon if link is image
          var icon;
          if ($(this).attr('href').match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*\.(?:jpg|gif|png))(?:\?([^#]*))?(?:#(.*))?/i)) {
            icon = ' ';
          } else {
            icon = ' ';
          }

          $(this).html (icon + domain);

        }

      });

      // remove sups
      // sups causes problem with popovers
      $(contentObj).find ('sup').each (function () {
        $(this).after ($(this).html ());
        $(this).remove ();
      });

      return $(contentObj).html ();

    },

    initialize: function () {

      if (!this.has ('htmlDoc'))
        return;

      var htmlDoc = this.get ('htmlDoc');

      this.set ('rawContent', $(htmlDoc).find ('div.content').html ());
      this.set ('content', this.parseContent (this.get ('rawContent')));
      this.set ('creationTime',
                this.relativeTime(
                  $(htmlDoc).find ('time[itemprop="commentTime"]')
                            .attr ('datetime')));
      this.set ('id', $(htmlDoc).find ('footer').attr ('data-id'));
      this.set ('isFavorite',
                $(htmlDoc).find ('footer').attr ('data-isfavorite') == 'true'
                    ? true : false );
      this.set ('favoriteCount',
                parseInt (
                  $(htmlDoc).find ('footer').attr ('data-favorite-count'))
                );
      this.set ('author', $(htmlDoc).find ('address a').text ());
      this.set ('author_tags', UserTagHelper.getUserTags(this.get('author')));

    }

  });

  return Entry;

});
<commit_msg>show facetime-video glyphicon if domain is youtube<commit_after>
define([
  'jquery',
  'underscore',
  'backbone',
  'helpers/usertag'
], function ($, _, Backbone, UserTagHelper) {

  var Entry = Backbone.Model.extend ({

    defaults: {
      content: '',
      rawContent: '',
      creationTime: '',
      modifyTime: '',
      author: '',
      isFavorite: false,
      favoriteCount: 0,
    },

    relativeTime: function (time) {
      var current = new Date ();

      var msPerMinute = 60 * 1000;
      var msPerHour = msPerMinute * 60;
      var msPerDay = msPerHour * 24;
      var msPerMonth = msPerDay * 30;
      var msPerYear = msPerDay * 365;

      // FIXME: need to check DST
      var elapsed = current - new Date (time) + (3*60*60*1000);

      if (elapsed < msPerMinute) {
        return Math.round (elapsed/1000) + ' saniye';
      }

      else if (elapsed < msPerHour) {
        return Math.round (elapsed/msPerMinute) + ' dakika';
      }

      else if (elapsed < msPerDay ) {
        return Math.round (elapsed/msPerHour ) + ' saat';
      }

      else if (elapsed < msPerMonth) {
        return Math.round (elapsed/msPerDay) + ' gün';
      }

      else if (elapsed < msPerYear) {
        return Math.round (elapsed/msPerMonth) + ' ay';
      }

      else {
        return Math.round (elapsed/msPerYear ) + ' yıl';
      }
    },

    parseContent: function (content) {

      var that = this;

      var contentObj = $.parseHTML ('
' + content + '
');

      $(contentObj).find ('a').each (function () {

        // EXTERNAL LINKS
        if ($(this).attr ('href').match (/^https?\:\/\//)) {

          var matches = $(this).attr ('href')
                               .match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
          var domain = matches && matches[1];
          domain = domain.replace (/^[^.]*\.(?=\w+\.\w+$)/, '');

          // show picture glyphicon if link is image
          // show facetime-video glyphicon if domain is youtube
          var icon;
          if ($(this).attr('href').match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*\.(?:jpg|gif|png))(?:\?([^#]*))?(?:#(.*))?/i)) {
            icon = ' ';
          } else if (domain == 'youtube.com') {
            icon = ' ';
          } else {
            icon = ' ';
          }

          $(this).html (icon + domain);

        }

      });

      // remove sups
      // sups causes problem with popovers
      $(contentObj).find ('sup').each (function () {
        $(this).after ($(this).html ());
        $(this).remove ();
      });

      return $(contentObj).html ();

    },

    initialize: function () {

      if (!this.has ('htmlDoc'))
        return;

      var htmlDoc = this.get ('htmlDoc');

      this.set ('rawContent', $(htmlDoc).find ('div.content').html ());
      this.set ('content', this.parseContent (this.get ('rawContent')));
      this.set ('creationTime',
                this.relativeTime(
                  $(htmlDoc).find ('time[itemprop="commentTime"]')
                            .attr ('datetime')));
      this.set ('id', $(htmlDoc).find ('footer').attr ('data-id'));
      this.set ('isFavorite',
                $(htmlDoc).find ('footer').attr ('data-isfavorite') == 'true'
                    ? true : false );
      this.set ('favoriteCount',
                parseInt (
                  $(htmlDoc).find ('footer').attr ('data-favorite-count'))
                );
      this.set ('author', $(htmlDoc).find ('address a').text ());
      this.set ('author_tags', UserTagHelper.getUserTags(this.get('author')));

    }

  });

  return Entry;

});
<|endoftext|>


<commit_before>import d3 from 'd3';
import lodash from 'lodash';
var _ = lodash;

import {
    Table,
    generate_headers,
    create_header_hopper,
    remove_hidden_from_matrix,
} from './utils';

import {
    generate_matrix_headers,
    generate_hidden_check,
    generate_hidden_index
} from './matrix_header';
import {get_dispatcher} from '../lib/converser';

export function FullTable(basetable) {
    /*
     Creates a clone of basetable
     and adds meta and header structures to the clone
     */
    let table = _.cloneDeep(basetable);
    table.meta = Table(table);
    table.base = basetable;

    table.hopper = {};
    _.map(table.stub, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.stub_size, table.meta.hops[heading]);
    });
    _.map(table.heading, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.heading_size, table.meta.hops[heading]);
    });

    table.row_headers = generate_matrix_headers(table, table.stub, table.meta.stub_size);
    table.heading_headers = generate_matrix_headers(table, table.heading,
        table.meta.heading_size);

    return table;
}

export function build() {
    let rtable = get_table('real');
    let visible_table = get_table('real');

    return [rtable, visible_table];
}

export function handle_visibility(table, original_table, heading, headers) {
    let new_headers = [];
    _.forOwn(headers, (hidden, header) => {
        if (!hidden) new_headers.push(header);
    });
    table.levels[heading] = new_headers;
    table.meta = Table(table);

    _.map(table.stub, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.stub_size, table.meta.hops[heading]);
    });

    _.map(table.heading, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.heading_size, table.meta.hops[heading]);
    });

    table.row_headers = generate_matrix_headers(table, table.stub, table.meta.stub_size);
    table.heading_headers = generate_matrix_headers(table, table.heading, table.meta.heading_size);
    let hidden_index = {
        heading: generate_hidden_index(original_table.heading_headers,
            table.heading_headers),
        stub: generate_hidden_index(original_table.row_headers,
            table.row_headers)
    };
    table.matrix = remove_hidden_from_matrix(
        original_table.matrix,
        hidden_index
    );
}

function hide_table() {

    let calc_table = {
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],

        matrix: _.range(8).map((i) => [1,2,3,4,5,6,7,8,9,10,11,i+1]),

        levels: {
            one: ['top heading 1'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1',],
            first: ['top row 2'],
            second: ['second row 1', 'second row 3', 'second row 4']
        }
    };

    calc_table.meta = Table(calc_table);

    calc_table.hopper = {
        one: create_header_hopper(calc_table.levels.one, calc_table.meta.heading_size, calc_table.meta.hops.one),
        two: create_header_hopper(calc_table.levels.two, calc_table.meta.heading_size, calc_table.meta.hops.two),
        three: create_header_hopper(calc_table.levels.three, calc_table.meta.heading_size, calc_table.meta.hops.three),
        first: create_header_hopper(calc_table.levels.first, calc_table.meta.stub_size, calc_table.meta.hops.first),
        second: create_header_hopper(calc_table.levels.second, calc_table.meta.stub_size, calc_table.meta.hops.second)
    };

    calc_table.row_headers = generate_matrix_headers(calc_table, calc_table.stub, calc_table.meta.stub_size);
    calc_table.heading_headers = generate_matrix_headers(calc_table, calc_table.heading, calc_table.meta.heading_size);

    return calc_table;
}

let SERVER = 'http://localhost:8000';
let ROUTER = {
    index: SERVER + '/',
    matrix: SERVER + '/matrix/'
};

function load_matrix(table) {
    d3.json(table.url, (err, data) => {
        SENTINEL[table.name] = false;
        if (err) console.log("problem fetching data", err);
        else {
            console.log("fetched some data", table.url)
            table.matrix = data;
            get_dispatcher('app').table_loaded(table.name);
        }
    });
}

/*
Sentinels are used to track ongoing network request
 */
let SENTINEL = {};
export function get_table(tableid) {
    /*
    Function goes to find a table for a given Id
    and returns a FullTable from it
     */
    let basetable = TABLES[tableid];

    let table = FullTable(basetable);
    if (!table.matrix) {
        if (!SENTINEL[table.name]) {
            SENTINEL[table.name] = true;
            load_matrix(table);
        }
    }
    return table;
}

export function fetch_table_previews(cb) {
    d3.json(ROUTER.index, (err, data) => {
        if (err) console.log("problem fetching tables", SERVER.index, err);
        else {
            console.log("fetched some tables");
            data.map((table, index) => {
                table.preview = true;
                TABLES[table.name] = table;
            });
            cb(); // this should render the app now that initialization is done
        }
    });
}

/*
Placeholder "database" for table meta and matrix
 */
export var TABLES = {
    test: {
        name: 'test',
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],
        levels: {
            one: ['top heading 1', 'top heading 2'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1', 'third heading 2'],
            first: ['top row 1', 'top row 2'],
            second: ['second row 1', 'second row 2', 'second row 3', 'second row 4']
        }
    }
}

export var OLD_TABLES = {
    real: {
        name: 'real',
        url: '/data/real.json',
        "heading": [
            "Sukupuoli",
            "Ikä"],
        "stub": [
            "Alue",
            "Vuosi"],
        "levels": {
            "Alue": [
                "Helsinki",
                "Espoo",
                "Vantaa",
                "Kauniainen"
            ],
            "Ikä": [
                "Väestö yhteensä",
                "0-vuotiaat",
                "1-vuotiaat",
                "2-vuotiaat"
            ],
            "Sukupuoli": [
                "Molemmat sukupuolet",
                "Miehet",
                "Naiset"
            ],
            "Vuosi": [
                "1976",
                "1977",
                "1978",
                "1979",
                "1980"]
        }
    },
    test: {
        name: 'test',
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],
        levels: {
            one: ['top heading 1', 'top heading 2'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1', 'third heading 2'],
            first: ['top row 1', 'top row 2'],
            second: ['second row 1', 'second row 2', 'second row 3', 'second row 4']
        }
    }
};
<commit_msg>Showing loaded preview tables works<commit_after>import d3 from 'd3';
import lodash from 'lodash';
var _ = lodash;

import {
    Table,
    generate_headers,
    create_header_hopper,
    remove_hidden_from_matrix,
} from './utils';

import {
    generate_matrix_headers,
    generate_hidden_check,
    generate_hidden_index
} from './matrix_header';
import {get_dispatcher} from '../lib/converser';

export function FullTable(basetable) {
    /*
     Creates a clone of basetable
     and adds meta and header structures to the clone
     */
    let table = _.cloneDeep(basetable);
    table.meta = Table(table);
    table.base = basetable;

    table.hopper = {};
    _.map(table.stub, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.stub_size, table.meta.hops[heading]);
    });
    _.map(table.heading, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.heading_size, table.meta.hops[heading]);
    });

    table.row_headers = generate_matrix_headers(table, table.stub, table.meta.stub_size);
    table.heading_headers = generate_matrix_headers(table, table.heading,
        table.meta.heading_size);

    return table;
}

export function build() {
    let rtable = get_table('real');
    let visible_table = get_table('real');

    return [rtable, visible_table];
}

export function handle_visibility(table, original_table, heading, headers) {
    let new_headers = [];
    _.forOwn(headers, (hidden, header) => {
        if (!hidden) new_headers.push(header);
    });
    table.levels[heading] = new_headers;
    table.meta = Table(table);

    _.map(table.stub, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.stub_size, table.meta.hops[heading]);
    });

    _.map(table.heading, (heading, index) => {
        table.hopper[heading] = create_header_hopper(table.levels[heading],
            table.meta.heading_size, table.meta.hops[heading]);
    });

    table.row_headers = generate_matrix_headers(table, table.stub, table.meta.stub_size);
    table.heading_headers = generate_matrix_headers(table, table.heading, table.meta.heading_size);
    let hidden_index = {
        heading: generate_hidden_index(original_table.heading_headers,
            table.heading_headers),
        stub: generate_hidden_index(original_table.row_headers,
            table.row_headers)
    };
    table.matrix = remove_hidden_from_matrix(
        original_table.matrix,
        hidden_index
    );
}

function hide_table() {

    let calc_table = {
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],

        matrix: _.range(8).map((i) => [1,2,3,4,5,6,7,8,9,10,11,i+1]),

        levels: {
            one: ['top heading 1'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1',],
            first: ['top row 2'],
            second: ['second row 1', 'second row 3', 'second row 4']
        }
    };

    calc_table.meta = Table(calc_table);

    calc_table.hopper = {
        one: create_header_hopper(calc_table.levels.one, calc_table.meta.heading_size, calc_table.meta.hops.one),
        two: create_header_hopper(calc_table.levels.two, calc_table.meta.heading_size, calc_table.meta.hops.two),
        three: create_header_hopper(calc_table.levels.three, calc_table.meta.heading_size, calc_table.meta.hops.three),
        first: create_header_hopper(calc_table.levels.first, calc_table.meta.stub_size, calc_table.meta.hops.first),
        second: create_header_hopper(calc_table.levels.second, calc_table.meta.stub_size, calc_table.meta.hops.second)
    };

    calc_table.row_headers = generate_matrix_headers(calc_table, calc_table.stub, calc_table.meta.stub_size);
    calc_table.heading_headers = generate_matrix_headers(calc_table, calc_table.heading, calc_table.meta.heading_size);

    return calc_table;
}

let SERVER = 'http://localhost:8000';
let ROUTER = {
    index: SERVER + '/',
    matrix: SERVER + '/matrix/'
};

function load_matrix(table) {
    d3.json(table.url, (err, data) => {
        SENTINEL[table.name] = false;
        if (err) console.log("problem fetching data", err);
        else {
            console.log("fetched some data", table.url)
            table.matrix = data;
            get_dispatcher('app').table_loaded(table.name);
        }
    });
}

/*
Sentinels are used to track ongoing network request
 */
let SENTINEL = {};
export function get_table(tableid) {
    /*
    Function goes to find a table for a given Id
    and returns a FullTable from it
     */
    let basetable = TABLES[tableid];

    let table = FullTable(basetable);
    if (!table.matrix) {
        if (!SENTINEL[table.name]) {
            SENTINEL[table.name] = true;
            load_matrix(table);
        }
    }
    return table;
}

export function fetch_table_previews(cb) {
    d3.json(ROUTER.index, (err, data) => {
        if (err) console.log("problem fetching tables", ROUTER.index, err);
        else {
            console.log("fetched some tables", data);
            _.map(data.pxdocs, (table, index) => {
                table.preview = true;
                TABLES[table.name] = table;
            });
            console.log(TABLES)
            cb(); // this should render the app now that initialization is done
        }
    });
}

/*
Placeholder "database" for table meta and matrix
 */
export var TABLES = {
    test: {
        name: 'test',
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],
        levels: {
            one: ['top heading 1', 'top heading 2'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1', 'third heading 2'],
            first: ['top row 1', 'top row 2'],
            second: ['second row 1', 'second row 2', 'second row 3', 'second row 4']
        },
        matrix: _.range(8).map((i) => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, i + 1])
    }
}

export var OLD_TABLES = {
    real: {
        name: 'real',
        url: '/data/real.json',
        "heading": [
            "Sukupuoli",
            "Ikä"],
        "stub": [
            "Alue",
            "Vuosi"],
        "levels": {
            "Alue": [
                "Helsinki",
                "Espoo",
                "Vantaa",
                "Kauniainen"
            ],
            "Ikä": [
                "Väestö yhteensä",
                "0-vuotiaat",
                "1-vuotiaat",
                "2-vuotiaat"
            ],
            "Sukupuoli": [
                "Molemmat sukupuolet",
                "Miehet",
                "Naiset"
            ],
            "Vuosi": [
                "1976",
                "1977",
                "1978",
                "1979",
                "1980"]
        }
    },
    test: {
        name: 'test',
        heading: ['one', 'two', 'three'],
        stub: ['first', 'second'],
        levels: {
            one: ['top heading 1', 'top heading 2'],
            two: ['second heading 1', 'second heading 2', 'second heading 3'],
            three: ['third heading 1', 'third heading 2'],
            first: ['top row 1', 'top row 2'],
            second: ['second row 1', 'second row 2', 'second row 3', 'second row 4']
        }
    }
};
<|endoftext|>


<commit_before>// var App = {
//     Views: {},
//     Controllers: {},
//     init: function() {
//         new App.Controllers.Tasks();
//         Backbone.history.start();
//     }
// };

//jQuery when DOM loads run this
$(function(){

  //Backbone Model

  window.Task = Backbone.Model.extend({
    url: function() {
      return this.id ? '/tasks/' + this.id : '/tasks'; //Ternary, look it up if you aren't sure
    },

    defaults: { task: {
      title: "Please enter a title",
			task_list_id: "",
			user_id: "",
			created_by: "",
			priority: false,
			completed: false,
			type: "",
			due_date: "",
      description: ""
    }},

    initialize: function(){
      //Can be used to initialize Model attributes
    },

    toggle: function() {
      this.save({completed: !this.get("completed")});
    },

    togglePriority: function() {
      this.save({priority: !this.get("priority")});
    }
  });

  //Collection

  window.TaskCollection = Backbone.Collection.extend({
    model: Task,
    url: '/tasks',

		comparator: function(task) {
			return task.get('completed');
		}

  });

  window.Tasks = new TaskCollection;

	//View

  window.TaskView = Backbone.View.extend({
    // tagName: "tr",
		tagName: "div",
		className: "task_holder",

    events: {
      //Can be used for handling events on the template
			"click .checkbox"             : "toggleDone",
			"click .flag"                 : "togglePriority"
    },

    initialize: function(){
      //this.render();
    },

    render: function(){
      var task = this.model.toJSON();
      //Template stuff goes here
      $(this.el).html(ich.task_template(task));
      return this;
    },

		toggleDone: function(){
			this.model.toggle();
		},

		togglePriority: function(){
			this.model.togglePriority();
			var flag = this.$(".flag");
			if (flag.hasClass('flag-active')){
				flag.removeClass('flag-active');
			} else {
				flag.addClass('flag-active');
			}
			return false
		}

  });

	window.AppView = Backbone.View.extend({

    el: $("#tasks_app"),

    events: {
      "submit form#create_task_form": "createTask",
			"click .opener"               : "openTask"
    },

    initialize: function(){
      _.bindAll(this, 'addOne', 'addAll');

      Tasks.bind('add', this.addOne);
      Tasks.bind('refresh', this.addAll);
      Tasks.bind('all', this.render);

      Tasks.fetch(); //This Gets the Model from the Server
    },

    addOne: function(task) {
      var view = new TaskView({model: task});
      // this.$("#task_table").append(view.render().el);
			this.$("#task_holder").append(view.render().el);
    },

    addAll: function(){
      Tasks.each(this.addOne);
    },

    newAttributes: function(event) {

      return { task: {
          task_list_id: event["task[task_list_id]"],
					user_id: event["task[user_id]"],
					created_by: event["task[created_by]"],
					priority: event["task[priority]"],
					completed: event["task[completed]"],
					type: event["type"],
					due_date: event["task[due_date]"],
					title: event["task[title]"],
          description: event["task[description]"]
        }}
    },

    createTask: function(e) {
      e.preventDefault(); //This prevents the form from submitting normally

			var values = {};
			$.each($('form#create_task_form').serializeArray(), function(i, field) {
			    values[field.name] = field.value;
			});

      var params = this.newAttributes(values);

			Tasks.create(params);

    },

		openTask: function(targ) {
			var id = targ.currentTarget.id;
			var opener = this.$("#slide_" + id);
			var slideSpeed = 500;
			var slideHolder = $("task_row_" + id);

			if (opener.hasClass('slide-active')){
				opener.css({overflow:'hidden'});
				opener.slideUp(slideSpeed);
				opener.removeClass('slide-active');
			} else {
				opener.slideDown(slideSpeed, function(){
					opener.css({overflow:'visibile'});
				})
				opener.addClass('slide-active');
			}

			return false; // Make sure it does not redirect anywhere
		}
  });

	window.App = new AppView;

});
<commit_msg>Grouping tasks by completed and due date<commit_after>// var App = {
//     Views: {},
//     Controllers: {},
//     init: function() {
//         new App.Controllers.Tasks();
//         Backbone.history.start();
//     }
// };

//jQuery when DOM loads run this
$(function(){

  //Backbone Model

  window.Task = Backbone.Model.extend({
    url: function() {
      return this.id ? '/tasks/' + this.id : '/tasks'; //Ternary, look it up if you aren't sure
    },

    defaults: { task: {
      title: "Please enter a title",
			task_list_id: "",
			user_id: "",
			created_by: "",
			priority: false,
			completed: false,
			type: "",
			due_date: "",
      description: ""
    }},

    initialize: function(){
      //Can be used to initialize Model attributes
    },

    toggle: function() {
      this.save({completed: !this.get("completed")});
    },

    togglePriority: function() {
      this.save({priority: !this.get("priority")});
    }
  });

  //Collection

  window.TaskCollection = Backbone.Collection.extend({
    model: Task,
    url: '/tasks',

		comparator: function(task) {
			return task.get('completed') + task.get('due_date');
		}

  });

  window.Tasks = new TaskCollection;

	//View

  window.TaskView = Backbone.View.extend({
    // tagName: "tr",
		tagName: "div",
		className: "task_holder",

    events: {
      //Can be used for handling events on the template
			"click .checkbox"             : "toggleDone",
			"click .flag"                 : "togglePriority"
    },

    initialize: function(){
      //this.render();
    },

    render: function(){
      var task = this.model.toJSON();
      //Template stuff goes here
      $(this.el).html(ich.task_template(task));
      return this;
    },

		toggleDone: function(){
			this.model.toggle();
		},

		togglePriority: function(){
			this.model.togglePriority();
			var flag = this.$(".flag");
			if (flag.hasClass('flag-active')){
				flag.removeClass('flag-active');
			} else {
				flag.addClass('flag-active');
			}
			return false
		}

  });

	window.AppView = Backbone.View.extend({

    el: $("#tasks_app"),

    events: {
      "submit form#create_task_form": "createTask",
			"click .opener"               : "openTask"
    },

    initialize: function(){
      _.bindAll(this, 'addOne', 'addAll');

      Tasks.bind('add', this.addOne);
      Tasks.bind('refresh', this.addAll);
      Tasks.bind('all', this.render);

      Tasks.fetch(); //This Gets the Model from the Server
    },

    addOne: function(task) {
      var view = new TaskView({model: task});
      // this.$("#task_table").append(view.render().el);
			this.$("#task_holder").append(view.render().el);
    },

    addAll: function(){
      Tasks.each(this.addOne);
    },

    newAttributes: function(event) {

      return { task: {
          task_list_id: event["task[task_list_id]"],
					user_id: event["task[user_id]"],
					created_by: event["task[created_by]"],
					priority: event["task[priority]"],
					completed: event["task[completed]"],
					type: event["type"],
					due_date: event["task[due_date]"],
					title: event["task[title]"],
          description: event["task[description]"]
        }}
    },

    createTask: function(e) {
      e.preventDefault(); //This prevents the form from submitting normally

			var values = {};
			$.each($('form#create_task_form').serializeArray(), function(i, field) {
			    values[field.name] = field.value;
			});

      var params = this.newAttributes(values);

			Tasks.create(params);

    },

		openTask: function(targ) {
			var id = targ.currentTarget.id;
			var opener = this.$("#slide_" + id);
			var slideSpeed = 500;
			var slideHolder = $("task_row_" + id);

			if (opener.hasClass('slide-active')){
				opener.css({overflow:'hidden'});
				opener.slideUp(slideSpeed);
				opener.removeClass('slide-active');
			} else {
				opener.slideDown(slideSpeed, function(){
					opener.css({overflow:'visibile'});
				})
				opener.addClass('slide-active');
			}

			return false; // Make sure it does not redirect anywhere
		}
  });

	window.App = new AppView;

});
<|endoftext|>


<commit_before>'use babel';

import TokenNavigationView from './token-navigation-view';
import fuzzy from 'fuzzy';
import { parse, toAtomRange } from './tokens-utils';

class FuzzyTokenView extends TokenNavigationView {

	createdCallback() {
		this.classList.add('token-navigation-fuzzy-token-view');

		const container = document.createElement('div');
		container.style.cssText = `
			padding: 10px;
		`;
		const wrapper = document.createElement('div');

		const header = document.createElement('header');
		header.style.cssText = `
			padding-bottom: 10px;
		`;

		this.headerTitle = document.createElement('span');

		this.nameEditor = document.createElement('atom-text-editor');
		this.nameEditor.setAttribute('mini', true);
		this.nameEditor.classList.add('fuzzy-view');

		// this.nameEditor.addEventListener('core:confirm', this.next.bind(this));
		this.nameEditor.addEventListener('core:cancel', () => this.hide());
		this.nameEditor.addEventListener('token-navigation:nextFuzzyToken', this.next.bind(this));
		this.nameEditor.addEventListener('token-navigation:previousFuzzyToken', this.previous.bind(this));
		this.nameEditor.addEventListener('token-navigation:allFuzzyToken', this.selectAll.bind(this))
		this.nameEditor.getModel().getBuffer().onDidChange(this.fuzzySearch.bind(this))
		this.nameEditor.onblur = this.updateUI.bind(this);
		this.nameEditor.onBlur = this.updateUI.bind(this);

		this.resultContainer = document.createElement('div');
		this.resultContainer.style.cssText = `
			min-width: 100px;
			text-align: right;
			padding-right: 5px;
			color: while;
		`;

		this.nameEditor.appendChild(this.resultContainer);
		header.appendChild(this.headerTitle);
		container.appendChild(header);
		wrapper.appendChild(this.nameEditor);
		container.appendChild(wrapper);
		this.appendChild(container);

		this.selectedToken = 0;
		this.ranges = [];

		this.updateUI();
	}

	fuzzySearch() {
		const fuzzyPattern = this.nameEditor.getModel().getBuffer().getText();
		const text = this.editor.getBuffer().getText();
		const tokens = parse(text);
		const tokenValues = tokens.map(t => t.value || t.type.label).map(String);
		if (fuzzyPattern.length < 3) {
			this.updateUI();
			return;
		}

		try {
			const results = fuzzy.filter(fuzzyPattern, tokenValues, {
				pre: '<',
				post: '>'
			});
			const ranges = results.map(t => tokens[t.index].loc).map(toAtomRange);
			this.selectedToken = 0;
			this.ranges = ranges;
			this.updateUI();
		} catch (e) {
			console.log(e);
		}
	}

	updateUI() {
		const fuzzyPattern = this.nameEditor.getModel().getBuffer().getText();

		if (this.ranges.length) {
			this.resultContainer.innerText = `${this.selectedToken + 1} of ${this.ranges.length}`;
			this.resultContainer.style.color = '#73c990';
		} else {
			this.resultContainer.style.color = fuzzyPattern >= 3 ? '#ff6347' : 'white';
			this.resultContainer.innerText = fuzzyPattern >= 3 ? 'No results'  : '';
		}

		if (fuzzyPattern.length < 3) {
			this.headerTitle.innerText = 'Fuzzy search tokens';
		} else {
			this.headerTitle.innerText = `${this.ranges.length} results for '${fuzzyPattern}'`;
		}

		if (this.nameEditor.classList.contains('is-focused')) {
			if (fuzzyPattern.length < 3) {
				this.nameEditor.style['border-color'] = '#568af2';
				this.nameEditor.style['box-shadow'] = '0 0 0 1px #568af2';
			} else {
				const finalColor = this.ranges.length ? '#73c990' : '#ff6347';
				this.nameEditor.style['border-color'] = finalColor;
				this.nameEditor.style['box-shadow'] = `0 0 0 1px ${finalColor}`;
			}
		} else {
			this.nameEditor.style['border-color'] = '';
			this.nameEditor.style['box-shadow'] = '';
		}

	}

	selectCurrent() {
			this.updateUI();
			if (!this.ranges.length) {
				return;
			}
			this.editor.setSelectedBufferRange(this.ranges[this.selectedToken]);
	}

	next() {
		this.selectedToken += 1;
		if (this.selectedToken >= this.ranges.length) {
			this.selectedToken = 0;
		}

		this.selectCurrent();
	}

	previous() {
		this.selectedToken -= 1;
		if (this.selectedToken <= 0) {
			this.selectedToken = this.ranges.length - 1;
		}

		this.selectCurrent();
	}

	show() {
		this.updateUI();
	}

	selectAll() {
		this.updateUI();
		if (!this.ranges.length) {
			return;
		}
		this.editor.setSelectedBufferRanges(this.ranges);
	}
}

export default document.registerElement('token-navigation-fuzzy-token-view', {
	prototype: FuzzyTokenView.prototype
});
<commit_msg>add eager search<commit_after>'use babel';

import TokenNavigationView from './token-navigation-view';
import fuzzy from 'fuzzy';
import { parse, toAtomRange } from './tokens-utils';

class FuzzyTokenView extends TokenNavigationView {

	createdCallback() {
		this.classList.add('token-navigation-fuzzy-token-view');

		const container = document.createElement('div');
		container.style.cssText = `
			padding: 10px;
		`;
		const wrapper = document.createElement('div');

		const header = document.createElement('header');
		header.style.cssText = `
			padding-bottom: 10px;
		`;

		this.headerTitle = document.createElement('span');

		this.nameEditor = document.createElement('atom-text-editor');
		this.nameEditor.setAttribute('mini', true);
		this.nameEditor.classList.add('fuzzy-view');

		// this.nameEditor.addEventListener('core:confirm', this.next.bind(this));
		this.nameEditor.addEventListener('core:cancel', () => this.hide());
		this.nameEditor.addEventListener('token-navigation:nextFuzzyToken', this.next.bind(this));
		this.nameEditor.addEventListener('token-navigation:previousFuzzyToken', this.previous.bind(this));
		this.nameEditor.addEventListener('token-navigation:allFuzzyToken', this.selectAll.bind(this))
		this.nameEditor.getModel().getBuffer().onDidChange(this.fuzzySearch.bind(this))
		this.nameEditor.onblur = this.updateUI.bind(this);
		this.nameEditor.onBlur = this.updateUI.bind(this);

		this.resultContainer = document.createElement('div');
		this.resultContainer.style.cssText = `
			min-width: 100px;
			text-align: right;
			padding-right: 5px;
			color: while;
		`;

		this.nameEditor.appendChild(this.resultContainer);
		header.appendChild(this.headerTitle);
		container.appendChild(header);
		wrapper.appendChild(this.nameEditor);
		container.appendChild(wrapper);
		this.appendChild(container);

		this.selectedToken = 0;
		this.ranges = [];

		this.updateUI();
	}

	fuzzySearch() {
		const fuzzyPattern = this.nameEditor.getModel().getBuffer().getText();
		const text = this.editor.getBuffer().getText();
		const tokens = parse(text);
		const tokenValues = tokens.map(t => t.value || t.type.label).map(String);
		if (fuzzyPattern.length < 3) {
			this.updateUI();
			return;
		}

		try {
			const results = fuzzy.filter(fuzzyPattern, tokenValues, {
				pre: '<',
				post: '>'
			});
			const ranges = results.map(t => tokens[t.index].loc).map(toAtomRange);
			this.selectedToken = 0;
			this.ranges = ranges;
			this.selectCurrent();
			this.updateUI();
		} catch (e) {
			console.log(e);
		}
	}

	updateUI() {
		const fuzzyPattern = this.nameEditor.getModel().getBuffer().getText();

		if (this.ranges.length) {
			this.resultContainer.innerText = `${this.selectedToken + 1} of ${this.ranges.length}`;
			this.resultContainer.style.color = '#73c990';
		} else {
			this.resultContainer.style.color = fuzzyPattern >= 3 ? '#ff6347' : 'white';
			this.resultContainer.innerText = fuzzyPattern >= 3 ? 'No results'  : '';
		}

		if (fuzzyPattern.length < 3) {
			this.headerTitle.innerText = 'Fuzzy search tokens';
		} else {
			this.headerTitle.innerText = `${this.ranges.length} results for '${fuzzyPattern}'`;
		}

		if (this.nameEditor.classList.contains('is-focused')) {
			if (fuzzyPattern.length < 3) {
				this.nameEditor.style['border-color'] = '#568af2';
				this.nameEditor.style['box-shadow'] = '0 0 0 1px #568af2';
			} else {
				const finalColor = this.ranges.length ? '#73c990' : '#ff6347';
				this.nameEditor.style['border-color'] = finalColor;
				this.nameEditor.style['box-shadow'] = `0 0 0 1px ${finalColor}`;
			}
		} else {
			this.nameEditor.style['border-color'] = '';
			this.nameEditor.style['box-shadow'] = '';
		}

	}

	selectCurrent() {
			this.updateUI();
			if (!this.ranges.length) {
				return;
			}
			this.editor.setSelectedBufferRange(this.ranges[this.selectedToken]);
	}

	next() {
		this.selectedToken += 1;
		if (this.selectedToken >= this.ranges.length) {
			this.selectedToken = 0;
		}

		this.selectCurrent();
	}

	previous() {
		this.selectedToken -= 1;
		if (this.selectedToken <= 0) {
			this.selectedToken = this.ranges.length - 1;
		}

		this.selectCurrent();
	}

	show() {
		this.updateUI();
	}

	selectAll() {
		this.updateUI();
		if (!this.ranges.length) {
			return;
		}
		this.editor.setSelectedBufferRanges(this.ranges);
	}
}

export default document.registerElement('token-navigation-fuzzy-token-view', {
	prototype: FuzzyTokenView.prototype
});
<|endoftext|>


<commit_before>/**
 * jKif - 2015
 * truth_tree_sent.js
 * @file TruthTreeSent Constructor
 * @author Clark Feusier - cfeusier@gmail.com
 * @copyright Copyright (C) Clark Feusier - All Rights Reserved
 */

var TruthTreeBase = require('./truth_tree_base'),
    _ = require('ramda'),
    nodeMod = require('./nodes/node_sent'),
    Node = nodeMod.NodeSent,
    NODE_TACTUS = nodeMod.NODE_TACTUS,
    STEP_TACTUS = 1,
    OPEN_STACK_TACTUS = 0,
    CLOSED_STACK_TACTUS = 0;

/**
 *
 * @public
 * @params {Array} kwBase
 * @constructor
 */
function TruthTreeSent(kwBase) {
  TruthTreeBase.call(this);
  this.openStacks[OPEN_STACK_TACTUS] = this.cleanTrunk(this.setupTrunk(kwBase));
  this.construct();
}

/**
 *
 * @public
 * @params {Array} trunk
 * @returns {Array[Node]}
 */
function cleanTrunk(trunk) {
  return _.uniqWith(this.compareNodes)(trunk);
}

/**
 *
 * @public
 * @params {Object} nodeA
 * @params {Object} nodeB
 * @returns {Boolean}
 */
function compareNodes(nodeA, nodeB) {
  return _.eq(nodeA.checked, nodeB.checked) && _.eqDeep(nodeA.proposition, nodeB.proposition);
}

/**
 *
 * @public
 * @params {Array} kwBase
 * @returns {Array[Node]}
 */
function setupTrunk(kwBase) {
  return kwBase.map(this.createGenericNode.bind(this));
}

/**
 *
 * @public
 * @params {Object} proposition
 * @returns {Node}
 */
function createGenericNode(proposition) {
  return new Node(this.propCleaner(proposition), STEP_TACTUS++);
}

/**
 *
 * @public
 * @params {Object} proposition
 * @returns {Object}
 */
function propCleaner(proposition) {
  return this.recursiveClean(proposition, {});
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 * @params {Object} memo
 * @returns {Object}
 */
function recursiveClean(propOrList, memo) {
  if (_.has('locationData', propOrList)) delete propOrList['locationData'];
  this.continueCleaning(propOrList, memo);
  return _.merge(memo, propOrList);
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 */
function continueCleaning(propOrList, memo) {
  if (_.type(propOrList) === 'Array') {
    propOrList.forEach(this.cleanDeep.bind(this, memo));
  } else if (_.type(propOrList) === 'Object') {
    for (var key in propOrList) this.cleanDeep(memo, propOrList[key]);
  }
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 */
function cleanDeep(memo, propOrList) {
  if (_.type(propOrList) !== 'String') this.recursiveClean(propOrList, memo);
}

/**
 *
 * @public
 */
function checkOpenStacks() {
  this.eachOpenStack(this.manageStack.bind(this));
  if (this.isTreeDead()) return true;
}

/**
 *
 * @public
 * @params {Array} stack
 * @params {String} key
 */
function moveStack(stack, key) {
  this.closedStacks[CLOSED_STACK_TACTUS++] = stack;
  delete this.openStacks[key];
}

/**
 *
 * @public
 * @params {Array} stack
 * @params {String} key
 */
function manageStack(stack, key) {
  if (this.isClosed(stack)) this.moveStack(stack, key);
}

/**
 *
 * @public
 * @param {Array} stack
 * @returns {Boolean}
 */
function isClosed(stack) {
  var ids = _.pluck('_id')(_.filter(this.isReduced, stack));
  return _.reduce(this.isContradiction.bind(this, ids), false, ids);
}

/**
 *
 * @public
 * @param {Array} ids
 * @param {Boolean} terminated
 * @param {Number} nodeId
 * @returns {Boolean}
 */
function isContradiction(ids, terminated, nodeId) {
  return nodeId > 0 ? _.contains(-nodeId)(ids) : _.contains(nodeId)(ids);
}

/**
 *
 * @public
 * @param {Node} node
 * @returns {Boolean}
 */
function isReduced(node) {
  return node.checked && _.type(node._id) === 'Number';
}

/**
 *
 * @public
 * @returns {Boolean}
 */
function isTreeDead() {
  return Object.keys(this.openStacks).length === 0;
}

/**
 *
 * @public
 */
function construct() {
  this.eachOpenStack(this.constructFromStack.bind(this));
}

/**
 *
 * @public
 * @params {Array} stack
 */
function constructFromStack(stack) {
  var checked = false;
  while (stack.length && !checked) {
    stack.forEach(this.deconstructNode.bind(this));
    checked = stack.reduce(function(allChecked, node) {
      return allChecked && node.checked;
    }, true);
  }
}

/**
 *
 * @public
 * @params {Object} node
 */
function deconstructNode(node) {
  if (!node.checked) {
    var newNodes = node.decompose();
    if (this.checkOpenStacks()) return;
    if (newNodes.length) {
      switch (newNodes[0]) {
        case 'negation':
          this.addToAllOpenStacks(this.createNegationNode(newNodes[1], node.line));
          break;
        case 'conjunction':
          this.addToAllOpenStacks(this.createConjunctionNodes(newNodes[1], node.line));
          break;
        case 'disjunction':
          break;
        case 'implication':
          break;
        case 'equivalence':
          break;
        default:
          break;
      }
    }
  }
}

/**
 *
 * @public
 * @params {Object} nodeData
 * @params {Number} rLine
 * @returns {Node}
 */
function createNegationNode(nodeData, rLine) {
  var newNode = new Node(nodeData, STEP_TACTUS++, { fromLine: rLine, name: 'negationDecomposition' });
  this.eachOpenStack(function(stack) {
    stack.forEach(function(node) {
      if (_.eqDeep(nodeData, node.proposition)) newNode._id = -node._id;
    });
  });
  return [newNode];
}

/**
 *
 * @public
 * @params {Object} nodeData
 * @params {Number} rLine
 * @returns {Node}
 */
function createConjunctionNodes(nodeData, rLine) {
  var rRule = { fromLine: rLine, name: 'conjunctionDecomposition' };
  return [new Node(nodeData[0], STEP_TACTUS++, rRule), new Node(nodeData[1], STEP_TACTUS++, rRule)];
}

/**
 *
 * @public
 * @params {Node} newNode
 */
function addToAllOpenStacks(newNodeOrNodes) {
  newNodeOrNodes.forEach(function(newNode) {
    this.eachOpenStack(function(stack) {
      stack.push(newNode);
    });
  }.bind(this));
}

/**
 *
 * @public
 * @params {Function} cb
 */
function eachOpenStack(cb) {
  for (var key in this.openStacks) {
    cb(this.openStacks[key], key);
  }
}

TruthTreeSent.STEP_TACTUS = STEP_TACTUS;

/**
 *
 * @description prototype setup, constructor cleanup, and method delegation
 */
TruthTreeSent.prototype = Object.create(TruthTreeBase.prototype);
TruthTreeSent.prototype.constructor = TruthTreeSent;
TruthTreeSent.prototype.setupTrunk = setupTrunk;
TruthTreeSent.prototype.createGenericNode = createGenericNode;
TruthTreeSent.prototype.construct = construct;
TruthTreeSent.prototype.constructFromStack = constructFromStack;
TruthTreeSent.prototype.deconstructNode = deconstructNode;
TruthTreeSent.prototype.cleanTrunk = cleanTrunk;
TruthTreeSent.prototype.recursiveClean = recursiveClean;
TruthTreeSent.prototype.cleanDeep = cleanDeep;
TruthTreeSent.prototype.continueCleaning = continueCleaning;
TruthTreeSent.prototype.compareNodes = compareNodes;
TruthTreeSent.prototype.propCleaner = propCleaner;
TruthTreeSent.prototype.addToAllOpenStacks = addToAllOpenStacks;
TruthTreeSent.prototype.createNegationNode = createNegationNode;
TruthTreeSent.prototype.createConjunctionNodes = createConjunctionNodes;
TruthTreeSent.prototype.checkOpenStacks = checkOpenStacks;
TruthTreeSent.prototype.isClosed = isClosed;
TruthTreeSent.prototype.isTreeDead = isTreeDead;
TruthTreeSent.prototype.isReduced = isReduced;
TruthTreeSent.prototype.isContradiction = isContradiction;
TruthTreeSent.prototype.eachOpenStack = eachOpenStack;
TruthTreeSent.prototype.moveStack = moveStack;
TruthTreeSent.prototype.manageStack = manageStack;

/**
 *
 * @type {TruthTreeSent}
 */
module.exports = TruthTreeSent;
<commit_msg>Fix open stack tactus bug<commit_after>/**
 * jKif - 2015
 * truth_tree_sent.js
 * @file TruthTreeSent Constructor
 * @author Clark Feusier - cfeusier@gmail.com
 * @copyright Copyright (C) Clark Feusier - All Rights Reserved
 */

var TruthTreeBase = require('./truth_tree_base'),
    _ = require('ramda'),
    nodeMod = require('./nodes/node_sent'),
    Node = nodeMod.NodeSent,
    NODE_TACTUS = nodeMod.NODE_TACTUS,
    STEP_TACTUS = 1,
    OPEN_STACK_TACTUS = 0,
    CLOSED_STACK_TACTUS = 0;

/**
 *
 * @public
 * @params {Array} kwBase
 * @constructor
 */
function TruthTreeSent(kwBase) {
  OPEN_STACK_TACTUS = 0;
  TruthTreeBase.call(this);
  this.openStacks[OPEN_STACK_TACTUS++] = this.cleanTrunk(this.setupTrunk(kwBase));
  this.construct();
}

/**
 *
 * @public
 * @params {Array} trunk
 * @returns {Array[Node]}
 */
function cleanTrunk(trunk) {
  return _.uniqWith(this.compareNodes)(trunk);
}

/**
 *
 * @public
 * @params {Object} nodeA
 * @params {Object} nodeB
 * @returns {Boolean}
 */
function compareNodes(nodeA, nodeB) {
  return _.eq(nodeA.checked, nodeB.checked) && _.eqDeep(nodeA.proposition, nodeB.proposition);
}

/**
 *
 * @public
 * @params {Array} kwBase
 * @returns {Array[Node]}
 */
function setupTrunk(kwBase) {
  return kwBase.map(this.createGenericNode.bind(this));
}

/**
 *
 * @public
 * @params {Object} proposition
 * @returns {Node}
 */
function createGenericNode(proposition) {
  return new Node(this.propCleaner(proposition), STEP_TACTUS++);
}

/**
 *
 * @public
 * @params {Object} proposition
 * @returns {Object}
 */
function propCleaner(proposition) {
  return this.recursiveClean(proposition, {});
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 * @params {Object} memo
 * @returns {Object}
 */
function recursiveClean(propOrList, memo) {
  if (_.has('locationData', propOrList)) delete propOrList['locationData'];
  this.continueCleaning(propOrList, memo);
  return _.merge(memo, propOrList);
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 */
function continueCleaning(propOrList, memo) {
  if (_.type(propOrList) === 'Array') {
    propOrList.forEach(this.cleanDeep.bind(this, memo));
  } else if (_.type(propOrList) === 'Object') {
    for (var key in propOrList) this.cleanDeep(memo, propOrList[key]);
  }
}

/**
 *
 * @public
 * @params {Object|Array} propOrList
 */
function cleanDeep(memo, propOrList) {
  if (_.type(propOrList) !== 'String') this.recursiveClean(propOrList, memo);
}

/**
 *
 * @public
 */
function checkOpenStacks() {
  this.eachOpenStack(this.manageStack.bind(this));
  if (this.isTreeDead()) return true;
}

/**
 *
 * @public
 * @params {Array} stack
 * @params {String} key
 */
function moveStack(stack, key) {
  this.closedStacks[CLOSED_STACK_TACTUS++] = stack;
  delete this.openStacks[key];
}

/**
 *
 * @public
 * @params {Array} stack
 * @params {String} key
 */
function manageStack(stack, key) {
  if (this.isClosed(stack)) this.moveStack(stack, key);
}

/**
 *
 * @public
 * @param {Array} stack
 * @returns {Boolean}
 */
function isClosed(stack) {
  var ids = _.pluck('_id')(_.filter(this.isReduced, stack));
  return _.reduce(this.isContradiction.bind(this, ids), false, ids);
}

/**
 *
 * @public
 * @param {Array} ids
 * @param {Boolean} terminated
 * @param {Number} nodeId
 * @returns {Boolean}
 */
function isContradiction(ids, terminated, nodeId) {
  return nodeId > 0 ? _.contains(-nodeId)(ids) : _.contains(nodeId)(ids);
}

/**
 *
 * @public
 * @param {Node} node
 * @returns {Boolean}
 */
function isReduced(node) {
  return node.checked && _.type(node._id) === 'Number';
}

/**
 *
 * @public
 * @returns {Boolean}
 */
function isTreeDead() {
  return Object.keys(this.openStacks).length === 0;
}

/**
 *
 * @public
 */
function construct() {
  this.eachOpenStack(this.constructFromStack.bind(this));
}

/**
 *
 * @public
 * @params {Array} stack
 */
function constructFromStack(stack) {
  var checked = false;
  while (stack.length && !checked) {
    stack.forEach(this.deconstructNode.bind(this));
    checked = stack.reduce(function(allChecked, node) {
      return allChecked && node.checked;
    }, true);
  }
}

/**
 *
 * @public
 * @params {Object} node
 */
function deconstructNode(node) {
  if (!node.checked) {
    var newNodes = node.decompose();
    if (this.checkOpenStacks()) return;
    if (newNodes.length) {
      switch (newNodes[0]) {
        case 'negation':
          this.addToAllOpenStacks(this.createNegationNode(newNodes[1], node.line));
          break;
        case 'conjunction':
          this.addToAllOpenStacks(this.createConjunctionNodes(newNodes[1], node.line));
          break;
        case 'disjunction':
          break;
        case 'implication':
          break;
        case 'equivalence':
          break;
        default:
          break;
      }
    }
  }
}

/**
 *
 * @public
 * @params {Object} nodeData
 * @params {Number} rLine
 * @returns {Node}
 */
function createNegationNode(nodeData, rLine) {
  var newNode = new Node(nodeData, STEP_TACTUS++, { fromLine: rLine, name: 'negationDecomposition' });
  this.eachOpenStack(function(stack) {
    stack.forEach(function(node) {
      if (_.eqDeep(nodeData, node.proposition)) newNode._id = -node._id;
    });
  });
  return [newNode];
}

/**
 *
 * @public
 * @params {Object} nodeData
 * @params {Number} rLine
 * @returns {Node}
 */
function createConjunctionNodes(nodeData, rLine) {
  var rRule = { fromLine: rLine, name: 'conjunctionDecomposition' };
  return [new Node(nodeData[0], STEP_TACTUS++, rRule), new Node(nodeData[1], STEP_TACTUS++, rRule)];
}

/**
 *
 * @public
 * @params {Node} newNode
 */
function addToAllOpenStacks(newNodeOrNodes) {
  newNodeOrNodes.forEach(function(newNode) {
    this.eachOpenStack(function(stack) {
      stack.push(newNode);
    });
  }.bind(this));
}

/**
 *
 * @public
 * @params {Function} cb
 */
function eachOpenStack(cb) {
  for (var key in this.openStacks) {
    cb(this.openStacks[key], key);
  }
}

TruthTreeSent.STEP_TACTUS = STEP_TACTUS;

/**
 *
 * @description prototype setup, constructor cleanup, and method delegation
 */
TruthTreeSent.prototype = Object.create(TruthTreeBase.prototype);
TruthTreeSent.prototype.constructor = TruthTreeSent;
TruthTreeSent.prototype.setupTrunk = setupTrunk;
TruthTreeSent.prototype.createGenericNode = createGenericNode;
TruthTreeSent.prototype.construct = construct;
TruthTreeSent.prototype.constructFromStack = constructFromStack;
TruthTreeSent.prototype.deconstructNode = deconstructNode;
TruthTreeSent.prototype.cleanTrunk = cleanTrunk;
TruthTreeSent.prototype.recursiveClean = recursiveClean;
TruthTreeSent.prototype.cleanDeep = cleanDeep;
TruthTreeSent.prototype.continueCleaning = continueCleaning;
TruthTreeSent.prototype.compareNodes = compareNodes;
TruthTreeSent.prototype.propCleaner = propCleaner;
TruthTreeSent.prototype.addToAllOpenStacks = addToAllOpenStacks;
TruthTreeSent.prototype.createNegationNode = createNegationNode;
TruthTreeSent.prototype.createConjunctionNodes = createConjunctionNodes;
TruthTreeSent.prototype.checkOpenStacks = checkOpenStacks;
TruthTreeSent.prototype.isClosed = isClosed;
TruthTreeSent.prototype.isTreeDead = isTreeDead;
TruthTreeSent.prototype.isReduced = isReduced;
TruthTreeSent.prototype.isContradiction = isContradiction;
TruthTreeSent.prototype.eachOpenStack = eachOpenStack;
TruthTreeSent.prototype.moveStack = moveStack;
TruthTreeSent.prototype.manageStack = manageStack;

/**
 *
 * @type {TruthTreeSent}
 */
module.exports = TruthTreeSent;
<|endoftext|>


<commit_before>// @ts-nocheck

'use strict';

const addEmptyLineBefore = require('../../utils/addEmptyLineBefore');
const getPreviousNonSharedLineCommentNode = require('../../utils/getPreviousNonSharedLineCommentNode');
const hasEmptyLine = require('../../utils/hasEmptyLine');
const isAfterSingleLineComment = require('../../utils/isAfterSingleLineComment');
const isFirstNested = require('../../utils/isFirstNested');
const isFirstNodeOfRoot = require('../../utils/isFirstNodeOfRoot');
const isSingleLineString = require('../../utils/isSingleLineString');
const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
const optionsMatches = require('../../utils/optionsMatches');
const removeEmptyLinesBefore = require('../../utils/removeEmptyLinesBefore');
const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');

const ruleName = 'rule-empty-line-before';

const messages = ruleMessages(ruleName, {
	expected: 'Expected empty line before rule',
	rejected: 'Unexpected empty line before rule',
});

function rule(expectation, options, context) {
	return (root, result) => {
		const validOptions = validateOptions(
			result,
			ruleName,
			{
				actual: expectation,
				possible: ['always', 'never', 'always-multi-line', 'never-multi-line'],
			},
			{
				actual: options,
				possible: {
					ignore: ['after-comment', 'first-nested', 'inside-block'],
					except: [
						'after-rule',
						'after-single-line-comment',
						'first-nested',
						'inside-block-and-after-rule',
						'inside-block',
					],
				},
				optional: true,
			},
		);

		if (!validOptions) {
			return;
		}

		root.walkRules((ruleNode) => {
			if (!isStandardSyntaxRule(ruleNode)) {
				return;
			}

			// Ignore the first node
			if (isFirstNodeOfRoot(ruleNode)) {
				return;
			}

			// Optionally ignore the expectation if a comment precedes this node
			if (
				optionsMatches(options, 'ignore', 'after-comment') &&
				ruleNode.prev() &&
				ruleNode.prev().type === 'comment'
			) {
				return;
			}

			// Optionally ignore the node if it is the first nested
			if (optionsMatches(options, 'ignore', 'first-nested') && isFirstNested(ruleNode)) {
				return;
			}

			const isNested = ruleNode.parent.type !== 'root';

			// Optionally ignore the expectation if inside a block
			if (optionsMatches(options, 'ignore', 'inside-block') && isNested) {
				return;
			}

			// Ignore if the expectation is for multiple and the rule is single-line
			if (expectation.includes('multi-line') && isSingleLineString(ruleNode.toString())) {
				return;
			}

			let expectEmptyLineBefore = Boolean(expectation.includes('always'));

			// Optionally reverse the expectation if any exceptions apply
			if (
				(optionsMatches(options, 'except', 'first-nested') && isFirstNested(ruleNode)) ||
				(optionsMatches(options, 'except', 'after-rule') && isAfterRule(ruleNode)) ||
				(optionsMatches(options, 'except', 'inside-block-and-after-rule') &&
					isNested &&
					isAfterRule(ruleNode)) ||
				(optionsMatches(options, 'except', 'after-single-line-comment') &&
					isAfterSingleLineComment(ruleNode)) ||
				(optionsMatches(options, 'except', 'inside-block') && isNested)
			) {
				expectEmptyLineBefore = !expectEmptyLineBefore;
			}

			const hasEmptyLineBefore = hasEmptyLine(ruleNode.raws.before);

			// Return if the expectation is met
			if (expectEmptyLineBefore === hasEmptyLineBefore) {
				return;
			}

			// Fix
			if (context.fix) {
				if (expectEmptyLineBefore) {
					addEmptyLineBefore(ruleNode, context.newline);
				} else {
					removeEmptyLinesBefore(ruleNode, context.newline);
				}

				return;
			}

			const message = expectEmptyLineBefore ? messages.expected : messages.rejected;

			report({
				message,
				node: ruleNode,
				result,
				ruleName,
			});
		});
	};
}

function isAfterRule(ruleNode) {
	const prevNode = getPreviousNonSharedLineCommentNode(ruleNode);

	return prevNode && prevNode.type === 'rule';
}

rule.ruleName = ruleName;
rule.messages = messages;
module.exports = rule;
<commit_msg>Refactor to improve types for `rule-empty-line-before` rule (#5834)<commit_after>'use strict';

const addEmptyLineBefore = require('../../utils/addEmptyLineBefore');
const getPreviousNonSharedLineCommentNode = require('../../utils/getPreviousNonSharedLineCommentNode');
const hasEmptyLine = require('../../utils/hasEmptyLine');
const isAfterSingleLineComment = require('../../utils/isAfterSingleLineComment');
const isFirstNested = require('../../utils/isFirstNested');
const isFirstNodeOfRoot = require('../../utils/isFirstNodeOfRoot');
const isSingleLineString = require('../../utils/isSingleLineString');
const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
const optionsMatches = require('../../utils/optionsMatches');
const removeEmptyLinesBefore = require('../../utils/removeEmptyLinesBefore');
const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');

const ruleName = 'rule-empty-line-before';

const messages = ruleMessages(ruleName, {
	expected: 'Expected empty line before rule',
	rejected: 'Unexpected empty line before rule',
});

/** @type {import('stylelint').Rule} */
const rule = (primary, secondaryOptions, context) => {
	return (root, result) => {
		const validOptions = validateOptions(
			result,
			ruleName,
			{
				actual: primary,
				possible: ['always', 'never', 'always-multi-line', 'never-multi-line'],
			},
			{
				actual: secondaryOptions,
				possible: {
					ignore: ['after-comment', 'first-nested', 'inside-block'],
					except: [
						'after-rule',
						'after-single-line-comment',
						'first-nested',
						'inside-block-and-after-rule',
						'inside-block',
					],
				},
				optional: true,
			},
		);

		if (!validOptions) {
			return;
		}

		const expectation = /** @type {string} */ (primary);

		root.walkRules((ruleNode) => {
			if (!isStandardSyntaxRule(ruleNode)) {
				return;
			}

			// Ignore the first node
			if (isFirstNodeOfRoot(ruleNode)) {
				return;
			}

			// Optionally ignore the expectation if a comment precedes this node
			if (optionsMatches(secondaryOptions, 'ignore', 'after-comment')) {
				const prevNode = ruleNode.prev();

				if (prevNode && prevNode.type === 'comment') {
					return;
				}
			}

			// Optionally ignore the node if it is the first nested
			if (optionsMatches(secondaryOptions, 'ignore', 'first-nested') && isFirstNested(ruleNode)) {
				return;
			}

			const isNested = ruleNode.parent && ruleNode.parent.type !== 'root';

			// Optionally ignore the expectation if inside a block
			if (optionsMatches(secondaryOptions, 'ignore', 'inside-block') && isNested) {
				return;
			}

			// Ignore if the expectation is for multiple and the rule is single-line
			if (expectation.includes('multi-line') && isSingleLineString(ruleNode.toString())) {
				return;
			}

			let expectEmptyLineBefore = expectation.includes('always');

			// Optionally reverse the expectation if any exceptions apply
			if (
				(optionsMatches(secondaryOptions, 'except', 'first-nested') && isFirstNested(ruleNode)) ||
				(optionsMatches(secondaryOptions, 'except', 'after-rule') && isAfterRule(ruleNode)) ||
				(optionsMatches(secondaryOptions, 'except', 'inside-block-and-after-rule') &&
					isNested &&
					isAfterRule(ruleNode)) ||
				(optionsMatches(secondaryOptions, 'except', 'after-single-line-comment') &&
					isAfterSingleLineComment(ruleNode)) ||
				(optionsMatches(secondaryOptions, 'except', 'inside-block') && isNested)
			) {
				expectEmptyLineBefore = !expectEmptyLineBefore;
			}

			const hasEmptyLineBefore = hasEmptyLine(ruleNode.raws.before);

			// Return if the expectation is met
			if (expectEmptyLineBefore === hasEmptyLineBefore) {
				return;
			}

			// Fix
			if (context.fix) {
				const newline = context.newline;

				if (typeof newline !== 'string') {
					throw new Error(`The "newline" property must be a string: ${newline}`);
				}

				if (expectEmptyLineBefore) {
					addEmptyLineBefore(ruleNode, newline);
				} else {
					removeEmptyLinesBefore(ruleNode, newline);
				}

				return;
			}

			const message = expectEmptyLineBefore ? messages.expected : messages.rejected;

			report({
				message,
				node: ruleNode,
				result,
				ruleName,
			});
		});
	};
};

/**
 * @param {import('postcss').Rule} ruleNode
 * @returns {boolean}
 */
function isAfterRule(ruleNode) {
	const prevNode = getPreviousNonSharedLineCommentNode(ruleNode);

	return prevNode != null && prevNode.type === 'rule';
}

rule.ruleName = ruleName;
rule.messages = messages;
module.exports = rule;
<|endoftext|>


<commit_before>AGORA = {
    agoraJS:null,
    agoraUserNotification:null,
    debounce:true
};

AGORA.init = function ()
{
    // Set datalet preview target
    ODE.commentTarget = "agora_datalet_preview";

    // agoraJS
    AGORA.initAgoraJS();

    // agoraUserNotification
    AGORA.agoraUserNotification = new agoraUserNotificationJS();

    // Set plugin preview to 'public-room'
    ODE.pluginPreview = 'public-room';

    // Handler for windows resize
    window.addEventListener("resize", function () {
    });

    // Handler for comment added
    $(window).on("comment_added", function(e){
        AGORA.onCommentAdded(e)
    });

    // Handle for click on send button (submit message)
    $("#agora_comment_send").click(function(){
        if(!AGORA.agoraJS.submit())
            OW.error("Messaggio vuoto");
    });

    // Handle for sentiment button
    $("#agora_sentiment_button").click(function(){
        AGORA.onAgoraSentimentButton();
    });

    // Handler for document ready (init perfectScrollbar, resize page, init autogrow)
    $(document).ready(function () {
        AGORA.onDocumentReady();
    });

    //Handler datalet creator button
    $('#agora_controllet_button').click(function(){
        previewFloatBox = OW.ajaxFloatBox('ODE_CMP_Preview', {} , {top:'56px', width:'calc(100vw - 112px)', height:'calc(100vh - 112px)', iconClass: 'ow_ic_add', title: ''});
    });

    //Handler mySpace button
    $('#agora_myspace_button').click(function(){
        previewFloatBox = OW.ajaxFloatBox('SPODPR_CMP_PrivateRoomCardViewer', {} , {top:'56px', width:'calc(100vw - 112px)', height:'calc(70vh)', iconClass: 'ow_ic_add', title: ''});
    });

    //Handler unreaded message section
    $('.agora_day_tab').click(function(e){
        AGORA.openDiv(e.currentTarget.id);
    });

    //Handle click on unread message
    $(".agora_unread_comment").click(function(e){
        AGORA.onClickUnreadComment(e);
    });

    // Handle preview
    $("#agora_preview_button").click(function () {
        AGORA.onPreviewButtonClick();
    });

    // Handle reply
    $(".agora_speech_reply").click(function (e) {
        AGORA.onReplyClick(e);
    });

    $("#user_notification_switch").on('click', function(e){
        AGORA.handleUserNotification(e);
    });

    // Handler realtime notification (socket.io)
    AGORA.handleRealtimeNotification();
};

AGORA.handleUserNotification = function (e) {
    AGORA.agoraUserNotification.handleUserNotification($(e.currentTarget).is(':checked'));
};

AGORA.onReplyClick = function (e)
{
    AGORA.agoraJS.set_level_up();
    AGORA.agoraJS.set_parentId($(e.currentTarget).parents().eq(2).attr('id'));
    AGORA.agoraJS.get_nested_comment().then(AGORA.levelUp);
};

AGORA.levelUp = function (data)
{
    var anc = $("#agora_nested_comment");
    var ans = $("#agora_nested_speech_text");
    var ancc = $("#agora_nested_chat_container");

    ancc.html(data);

    $("#agora_back").click(function () {
        AGORA.levelDown().then(function(){ancc.html("");});
    });

    anc.mouseover(function () {
        ans.removeClass("agora_nested_speech_text");
    });

    anc.mouseout(function () {
        ans.addClass("agora_nested_speech_text");
    });

    return AGORA.fadeToPromise($("#agora_chat_container")[0], ancc[0]);
};

AGORA.levelDown = function ()
{
    AGORA.agoraJS.set_parentId(AGORA.roomId);
    AGORA.agoraJS.set_level_down();
    return AGORA.fadeToPromise($("#agora_nested_chat_container")[0], $("#agora_chat_container")[0]);
};

AGORA.switchLevel = function (data)
{
    var _data = data;

    var anc = $("#agora_nested_comment");
    var ans = $("#agora_nested_speech_text");
    var ancc = $("#agora_nested_chat_container");

    return $(ancc).animate({
        opacity: 0
    }, 250, function () {
        ancc.html(_data);
        $("#agora_back").click(function () {
            AGORA.levelDown().then(function(){ancc.html("");});
        });

        anc.mouseover(function () {
            ans.removeClass("agora_nested_speech_text");
        });

        anc.mouseout(function () {
            ans.addClass("agora_nested_speech_text");
        });
    }).animate({
        opacity: 1
    }, 250).promise();

};

AGORA.onPreviewButtonClick = function ()
{
    var elem = $("#agora_datalet_preview");
    elem.toggle();
    var e = elem.children()[1];
    $(e).context.behavior.redraw();
};

AGORA.initAgoraJS = function ()
{
    AGORA.agoraJS = new agoraJs();
    AGORA.agoraJS.init($("#agora_comment"),AGORA.roomId, AGORA.agora_comment_endpoint, AGORA.agora_nested_comment_endpoint);
    AGORA.agoraJS.set_string_handler(AGORA.string_handler);
};

AGORA.onCommentAdded = function (e)
{
    AGORA.scroll_to();

    var elem = $("#agora_datalet_placeholder_" + e.post_id);
    var parent_children = elem.parent().children()[0];
    $(parent_children).emoticonize();

    if(e.component != "") {
        elem.addClass("agora_fullsize_datalet " + e.component);
        $("#agora_preview_button").hide();
        ODE.reset();
    }

    $(elem).parent().find(".agora_speech_reply").click(function (e) {
        AGORA.onReplyClick(e);
    });
};

AGORA.onAgoraSentimentButton = function()
{
    var sb = $("#agora_sentiment_button");

    switch(AGORA.agoraJS.get_sentiment())
    {
        case 0 :
            sb.css('background', '#4CAF50 url("/ow_static/plugins/agora/images/sentiment-satisfied.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(1);
            break;

        case 1 :
            sb.css('background', '#F44336 url("/ow_static/plugins/agora/images/sentiment-dissatisfied.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(2);
            break;

        default :
            sb.css('background', '#9E9E9E url("/ow_static/plugins/agora/images/sentiment-neutral.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(0);
    }
};

AGORA.onDocumentReady = function ()
{
    $('#agora_chat_container').perfectScrollbar();
    $('#agora_nested_chat_container').perfectScrollbar();
    $(".agora_unread_comments").perfectScrollbar();
    $('#agora_comment').autogrow();
    AGORA.scroll_to();

    // Emoticonize !!
    $('.agora_speech_text').emoticonize();
};

// UNREAD
AGORA.onClickUnreadComment = function (e)
{
    var id       = e.currentTarget.id.replace("unread_", "");
    var parentId = e.currentTarget.getAttribute("parent-id").match(/\d+/)[0];

    if(AGORA.agoraJS.get_parentId() == parentId || AGORA.agoraJS.get_parentId() == parentId)
    {
        // da livello 0 a 0 o stesso nested level
        AGORA.highlightMessage(id);
    }
    else if(parentId == AGORA.roomId && AGORA.agoraJS.get_parentId() != AGORA.roomId)
    {
        // da livello 1 a 0
        AGORA.levelDown().then(AGORA.highlightMessage.bind(null,id));
    }
    else if(AGORA.agoraJS.get_parentId() != parentId && parentId != AGORA.roomId && AGORA.agoraJS.get_parentId() != AGORA.roomId)
    {
        // da livello 1 a 1
        AGORA.agoraJS.set_parentId(parentId);
        AGORA.agoraJS.get_nested_comment().then(AGORA.switchLevel).then(AGORA.highlightMessage.bind(null,id));
    }
    else
    {
        // da livello 0 a 1
        AGORA.agoraJS.set_level_up();
        AGORA.agoraJS.set_parentId(parentId);
        AGORA.agoraJS.get_nested_comment().then(AGORA.levelUp).then(AGORA.highlightMessage.bind(null,id));
    }

};

AGORA.highlightMessage = function(id)
{
    var as  = $("#" + id + " .agora_speech");
    AGORA.scroll_to(id);
    as.css("background-color", "#FFEB3B");

    setTimeout(
        function () {
            as.css("transition", "background-color 1s ease");
            as.css("background-color", "#EEEEEE");
        }, 100);

    setTimeout(
        function () {
            as.css("transition", "");
        }, 1100);
};

AGORA.handleRealtimeNotification = function ()
{
    // Handle realtime communication
    var socket = io(window.location.origin + ":3000");

    socket.emit('online_notification', {user_id:AGORA.user_id, room_id:AGORA.roomId, plugin:'spodpublic'});

    socket.on('online_notification_' + AGORA.roomId, function(data) {
        data.forEach(function(e){
            $("#user_avatar_"+e).addClass("online");
        });
    });

    socket.on('offline_notification', function(id) {
        $("#user_avatar_"+id).removeClass("online");
    });

    socket.on('realtime_message_' + AGORA.roomId, function(data) {

        var target;

        if(AGORA.user_id != data.user_id)
        {
            if(data.comment_level == 0)
                target = $("#agora_chat_container");
            else if(AGORA.agoraJS.get_parentId() == data.parent_id)
                target = $("#agora_nested_chat_container");
            else
                return;

            AGORA.agoraJS.add_rt_comment(target,
                AGORA.agora_static_resource_url + 'JSSnippet/rt_comment.tpl',
                [   data.message_id,
                    (data.sentiment == 0 ? 'neutral' : (data.sentiment == 1 ?'satisfied' : 'dissatisfied')),
                    data.user_display_name,
                    data.user_url,
                    data.user_avatar,
                    data.comment,
                    data.message_id,
                    data.user_display_name,
                    'just now',
                    '0'],
                data.message_id, {component:data.component, params:data.params, fields:data.fields, data:''});
        }
    });
};

AGORA.scroll_to = function (id)
{
    var st;

    if(AGORA.agoraJS.get_parentId() == AGORA.roomId)
        st = $("#agora_chat_container");
    else
        st = $("#agora_nested_chat_container");

    if(id)
        st.scrollTop(st.scrollTop() + $("#" + id).position().top);
    else
        st.scrollTop(st.prop("scrollHeight"));

    st.perfectScrollbar('update');
};

AGORA.openDiv = function (tab_id)
{
    var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 56 - 345;

    var tab_to_close = $(".agora_tab_opened")[0];
    var tab_to_open = $(".agora_unread_comments")[tab_id];

    if (AGORA.debounce && tab_to_open != tab_to_close) {
        AGORA.debounce = false;

        $(tab_to_close).animate({ //close
            display: "none",
            opacity: 0,
            height: 0
        }, 1000);

        $(tab_to_open).css("display", "block");

        $(tab_to_open).animate({ //open
            display: "block",
            opacity: 1,
            height: h
        }, 1000);

        setTimeout(
            function () {
                $(tab_to_open).delay(0).addClass("agora_tab_opened");
                $(tab_to_close).delay(0).removeClass("agora_tab_opened");

                $(tab_to_close).css("display", "none");

                AGORA.debounce = true;
            }, 1000);
    }
};

AGORA.string_handler = function(string)
{
    return string.replace(/\n/g, "<br/>");
};

AGORA.fadeToPromise = function(from, to)
{
    $(to).show();

    $(from).animate({
        opacity: 0
    }, 250, function () {
        $(from).hide();
    });

    return $(to).delay(250).animate({
        opacity: 1
    }, 250).promise();
};

/*AGORA.resize = function()
 {
 var acc = $("#agora_chat_container");
 var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 250 - $('#agora_header_description').height();/!*fixed agora_header_description 48px now*!/

 acc.height(h);
 acc.scrollTop(acc.prop("scrollHeight"));
 acc.perfectScrollbar('update');
 };*/

<commit_msg>agora enhancement<commit_after>AGORA = {
    agoraJS:null,
    agoraUserNotification:null,
    debounce:true
};

AGORA.init = function ()
{
    // Set datalet preview target
    ODE.commentTarget = "agora_datalet_preview";

    // agoraJS
    AGORA.initAgoraJS();

    // agoraUserNotification
    AGORA.agoraUserNotification = new agoraUserNotificationJS();

    // Set plugin preview to 'public-room'
    ODE.pluginPreview = 'public-room';

    // Handler for windows resize
    window.addEventListener("resize", function () {
    });

    // Handler for comment added
    $(window).on("comment_added", function(e){
        AGORA.onCommentAdded(e)
    });

    // Handle for click on send button (submit message)
    $("#agora_comment_send").click(function(){
        if(!AGORA.agoraJS.submit())
            OW.error("Messaggio vuoto");
    });

    // Handle for sentiment button
    $("#agora_sentiment_button").click(function(){
        AGORA.onAgoraSentimentButton();
    });

    // Handler for document ready (init perfectScrollbar, resize page, init autogrow)
    $(document).ready(function () {
        AGORA.onDocumentReady();
    });

    //Handler datalet creator button
    $('#agora_controllet_button').click(function(){
        previewFloatBox = OW.ajaxFloatBox('ODE_CMP_Preview', {} , {top:'56px', width:'calc(100vw - 112px)', height:'calc(100vh - 112px)', iconClass: 'ow_ic_add', title: ''});
    });

    //Handler mySpace button
    $('#agora_myspace_button').click(function(){
        previewFloatBox = OW.ajaxFloatBox('SPODPR_CMP_PrivateRoomCardViewer', {} , {top:'56px', width:'calc(100vw - 112px)', height:'calc(70vh)', iconClass: 'ow_ic_add', title: ''});
    });

    //Handler unreaded message section
    $('.agora_day_tab').click(function(e){
        AGORA.openDiv(e.currentTarget.id);
    });

    //Handle click on unread message
    $(".agora_unread_comment").click(function(e){
        AGORA.onClickUnreadComment(e);
    });

    // Handle preview
    $("#agora_preview_button").click(function () {
        AGORA.onPreviewButtonClick();
    });

    // Handle reply
    $(".agora_speech_reply").click(function (e) {
        AGORA.onReplyClick(e);
    });

    $("#user_notification_switch").on('click', function(e){
        AGORA.handleUserNotification(e);
    });

    // Handler realtime notification (socket.io)
    AGORA.handleRealtimeNotification();
};

AGORA.handleUserNotification = function (e) {
    AGORA.agoraUserNotification.handleUserNotification($(e.currentTarget).is(':checked'));
};

AGORA.onReplyClick = function (e)
{
    AGORA.agoraJS.set_level_up();
    AGORA.agoraJS.set_parentId($(e.currentTarget).parents().eq(2).attr('id'));
    AGORA.agoraJS.get_nested_comment().then(AGORA.levelUp);
};

AGORA.levelUp = function (data)
{
    var anc = $("#agora_nested_comment");
    var ans = $("#agora_nested_speech_text");
    var ancc = $("#agora_nested_chat_container");

    ancc.html(data);

    $("#agora_back").click(function () {
        AGORA.levelDown().then(function(){ancc.html("");});
    });

    anc.mouseover(function () {
        ans.removeClass("agora_nested_speech_text");
    });

    anc.mouseout(function () {
        ans.addClass("agora_nested_speech_text");
    });

    return AGORA.fadeToPromise($("#agora_chat_container")[0], ancc[0]);
};

AGORA.levelDown = function ()
{
    AGORA.agoraJS.set_parentId(AGORA.roomId);
    AGORA.agoraJS.set_level_down();
    return AGORA.fadeToPromise($("#agora_nested_chat_container")[0], $("#agora_chat_container")[0]);
};

AGORA.switchLevel = function (data)
{
    var _data = data;

    var anc = $("#agora_nested_comment");
    var ans = $("#agora_nested_speech_text");
    var ancc = $("#agora_nested_chat_container");

    return $(ancc).animate({
        opacity: 0
    }, 250, function () {
        ancc.html(_data);
        $("#agora_back").click(function () {
            AGORA.levelDown().then(function(){ancc.html("");});
        });

        anc.mouseover(function () {
            ans.removeClass("agora_nested_speech_text");
        });

        anc.mouseout(function () {
            ans.addClass("agora_nested_speech_text");
        });
    }).animate({
        opacity: 1
    }, 250).promise();

};

AGORA.onPreviewButtonClick = function ()
{
    var elem = $("#agora_datalet_preview");
    elem.toggle();
    var e = elem.children()[1];
    $(e).context.behavior.redraw();
};

AGORA.initAgoraJS = function ()
{
    AGORA.agoraJS = new agoraJs();
    AGORA.agoraJS.init($("#agora_comment"),AGORA.roomId, AGORA.agora_comment_endpoint, AGORA.agora_nested_comment_endpoint);
    AGORA.agoraJS.set_string_handler(AGORA.string_handler);
};

AGORA.onCommentAdded = function (e)
{
    AGORA.scroll_to();

    var elem = $("#agora_datalet_placeholder_" + e.post_id);
    var parent_children = elem.parent().children()[0];
    $(parent_children).emoticonize();

    if(e.component != "") {
        elem.addClass("agora_fullsize_datalet " + e.component);
        $("#agora_preview_button").hide();
        ODE.reset();
    }

    $(elem).parent().find(".agora_speech_reply").click(function (e) {
        AGORA.onReplyClick(e);
    });
};

AGORA.onAgoraSentimentButton = function()
{
    var sb = $("#agora_sentiment_button");

    switch(AGORA.agoraJS.get_sentiment())
    {
        case 0 :
            sb.css('background', '#4CAF50 url("/ow_static/plugins/agora/images/sentiment-satisfied.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(1);
            break;

        case 1 :
            sb.css('background', '#F44336 url("/ow_static/plugins/agora/images/sentiment-dissatisfied.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(2);
            break;

        default :
            sb.css('background', '#9E9E9E url("/ow_static/plugins/agora/images/sentiment-neutral.svg") no-repeat 0 0');
            AGORA.agoraJS.set_sentiment(0);
    }
};

AGORA.onDocumentReady = function ()
{
    $('#agora_chat_container').perfectScrollbar();
    $('#agora_nested_chat_container').perfectScrollbar();
    $(".agora_unread_comments").perfectScrollbar();
    $('#agora_comment').autogrow();
    AGORA.scroll_to();

    // Emoticonize !!
    $('.agora_speech_text').emoticonize();
};

// UNREAD
AGORA.onClickUnreadComment = function (e)
{
    var id       = e.currentTarget.id.replace("unread_", "");
    var parentId = e.currentTarget.getAttribute("parent-id").match(/\d+/)[0];

    if(AGORA.agoraJS.get_parentId() == parentId || AGORA.agoraJS.get_parentId() == parentId)
    {
        // da livello 0 a 0 o stesso nested level
        AGORA.highlightMessage(id);
    }
    else if(parentId == AGORA.roomId && AGORA.agoraJS.get_parentId() != AGORA.roomId)
    {
        // da livello 1 a 0
        AGORA.levelDown().then(AGORA.highlightMessage.bind(null,id));
    }
    else if(AGORA.agoraJS.get_parentId() != parentId && parentId != AGORA.roomId && AGORA.agoraJS.get_parentId() != AGORA.roomId)
    {
        // da livello 1 a 1
        AGORA.agoraJS.set_parentId(parentId);
        AGORA.agoraJS.get_nested_comment().then(AGORA.switchLevel).then(AGORA.highlightMessage.bind(null,id));
    }
    else
    {
        // da livello 0 a 1
        AGORA.agoraJS.set_level_up();
        AGORA.agoraJS.set_parentId(parentId);
        AGORA.agoraJS.get_nested_comment().then(AGORA.levelUp).then(AGORA.highlightMessage.bind(null,id));
    }

};

AGORA.highlightMessage = function(id)
{
    var as  = $("#" + id + " .agora_speech");

    AGORA.scroll_to(id).then(function () {
        as.css("background-color", "#FFEB3B");

        setTimeout(
            function () {
                as.css("transition", "background-color 1s ease");
                as.css("background-color", "#EEEEEE");
            }, 100);

        setTimeout(
            function () {
                as.css("transition", "");
            }, 1100);
    });
};

AGORA.handleRealtimeNotification = function ()
{
    // Handle realtime communication
    var socket = io(window.location.origin + ":3000");

    socket.emit('online_notification', {user_id:AGORA.user_id, room_id:AGORA.roomId, plugin:'spodpublic'});

    socket.on('online_notification_' + AGORA.roomId, function(data) {
        data.forEach(function(e){
            $("#user_avatar_"+e).addClass("online");
        });
    });

    socket.on('offline_notification', function(id) {
        $("#user_avatar_"+id).removeClass("online");
    });

    socket.on('realtime_message_' + AGORA.roomId, function(data) {

        var target;

        if(AGORA.user_id != data.user_id)
        {
            if(data.comment_level == 0)
                target = $("#agora_chat_container");
            else if(AGORA.agoraJS.get_parentId() == data.parent_id)
                target = $("#agora_nested_chat_container");
            else
                return;

            AGORA.agoraJS.add_rt_comment(target,
                AGORA.agora_static_resource_url + 'JSSnippet/rt_comment.tpl',
                [   data.message_id,
                    (data.sentiment == 0 ? 'neutral' : (data.sentiment == 1 ?'satisfied' : 'dissatisfied')),
                    data.user_display_name,
                    data.user_url,
                    data.user_avatar,
                    data.comment,
                    data.message_id,
                    data.user_display_name,
                    'just now',
                    '0'],
                data.message_id, {component:data.component, params:data.params, fields:data.fields, data:''});
        }
    });
};

//scroll to element with id, if id empty scroll to bottom
AGORA.scroll_to = function (id)
{
    var st;

    if(AGORA.agoraJS.get_parentId() == AGORA.roomId)
        st = $("#agora_chat_container");
    else
        st = $("#agora_nested_chat_container");

    if(id)
        st.scrollTop(st.scrollTop() + $("#" + id).position().top);
    else
        st.scrollTop(st.prop("scrollHeight"));

    return st.perfectScrollbar('update').promise();
};

AGORA.openDiv = function (tab_id)
{
    var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 56 - 345;

    var tab_to_close = $(".agora_tab_opened")[0];
    var tab_to_open = $(".agora_unread_comments")[tab_id];

    if (AGORA.debounce && tab_to_open != tab_to_close) {
        AGORA.debounce = false;

        $(tab_to_close).animate({ //close
            display: "none",
            opacity: 0,
            height: 0
        }, 1000);

        $(tab_to_open).css("display", "block");

        $(tab_to_open).animate({ //open
            display: "block",
            opacity: 1,
            height: h
        }, 1000);

        setTimeout(
            function () {
                $(tab_to_open).delay(0).addClass("agora_tab_opened");
                $(tab_to_close).delay(0).removeClass("agora_tab_opened");

                $(tab_to_close).css("display", "none");

                AGORA.debounce = true;
            }, 1000);
    }
};

AGORA.string_handler = function(string)
{
    return string.replace(/\n/g, "<br/>");
};

AGORA.fadeToPromise = function(from, to)
{
    $(to).show();

    $(from).animate({
        opacity: 0
    }, 250, function () {
        $(from).hide();
    });

    return $(to).delay(250).animate({
        opacity: 1
    }, 250).promise();
};

/*AGORA.resize = function()
 {
 var acc = $("#agora_chat_container");
 var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 250 - $('#agora_header_description').height();/!*fixed agora_header_description 48px now*!/

 acc.height(h);
 acc.scrollTop(acc.prop("scrollHeight"));
 acc.perfectScrollbar('update');
 };*/

<|endoftext|>


<commit_before>var graphs = {};

var initDimensions = function(elementId) {
    // automatically size to the container using JQuery to get width/height
    width = $("#" + elementId).width();
    height = $("#" + elementId).height();

    // make sure to use offset() and not position() as we want it relative to
    // the document, not its parent
    xOffset = $("#" + elementId).offset().left;
    yOffset = $("#" + elementId).offset().top;
    return {width: width, height: height, xOffset: xOffset, yOffset: yOffset};
}

var drawTimeseries = function(trace, elementId, dataX, dataY) {
    // create an SVG element inside the element that fills 100% of the div
    var graph = d3.select("#" + elementId).append("svg:svg").attr("width", "100%")
            .attr("height", "100%");
    hoverContainer = $("#" + elementId + " svg");

    var dimensions = initDimensions(elementId);

    // X scale will fit values from 0-10 within range of pixels
    var x = d3.scale.linear().domain([_.min(dataX), _.max(dataX)]).range(
            [0, dimensions.width]);
    // Y scale will fit values from 0-10 within pixels 0-100
    var y = d3.scale.linear().domain([_.min(dataY), _.max(dataY)]).range(
            [dimensions.height, 0]);

    // create a line object that represents the SVG line we're creating
    var line = d3.svg.line()
    .x(function(d,i) {
        return x(d[0]);
    })
    .y(function(d) {
        return y(d[1]);
    })

    var hoverLineGroup = graph.append("svg:svg").attr("class", "hover-line");
    var hoverLine = hoverLineGroup.append("svg:line")
        .attr("x1", 10).attr("x2", 10)
        .attr("y1", 0).attr("y2", dimensions.height);
    hoverLine.classed("hide", true);

    var maxValue = _.max(dataY);
    var maxPosition = y(maxValue);
    var maxLineGroup = graph.append("svg:svg").attr("class", "max-line");
    var maxLine = maxLineGroup.append("svg:line")
        .attr("x1", 0).attr("x2", dimensions.width)
        .attr("y1", maxPosition).attr("y2", maxPosition);

    var average = _.reduce(dataY, function(memo, value) { return memo + value; },
            0) / dataY.length;
    var averageLineGroup = graph.append("svg:svg").attr("class", "average-line");
    var averageLine = averageLineGroup.append("svg:line")
        .attr("x1", 0).attr("x2", dimensions.width)
        .attr("y1", y(average)).attr("y2", y(average));
    var averageText = averageLineGroup.append("svg:text")
        .attr("x", 5).attr("y", y(average) - 8)
        .attr("text-anchor", "left")
        .text("avg");

    // display the line by appending an svg:path element with the data line we created above
    graph.append("svg:path").attr("d", line(_.zip(dataX, dataY)));

    var graphHolder = {elementId: elementId, graph: graph, x: x, y: y,
            hoverLine: hoverLine, dimensions: dimensions, dataX: dataX,
            dataY: dataY};

    $(hoverContainer).mouseleave(function(event) {
        handleMouseOutGraph(event);
    });

    $(hoverContainer).mousemove(function(event) {
        handleMouseOverGraph(event, trace, graphHolder);
    });

    return graphHolder;
}

var timeseriesHoverHandler = {
    on: function(timestamp, trace, mouseX, mouseY) {
        _.each(graphs, function(otherGraph, i) {
            otherGraph.hoverLine.classed("hide", false);

            // set position of hoverLine
            otherGraph.hoverLine.attr("x1", mouseX).attr("x2", mouseX)

            var hoveredValue = findClosestToX(timestamp,
                otherGraph.dataX, otherGraph.dataY)[1];
            $("#current_" + otherGraph.elementId).text(hoveredValue.toFixed(2)).parent().show();
        });
    },
    off: function() {
        _.each(graphs, function(graph, i) {
            graph.hoverLine.classed("hide", true);
            $("#current_" + graph.elementId).parent().hide();
        });
    }
}

var drawTimeseriesGraphs = function(trace) {
    _.each(["vehicle_speed", "engine_speed", "odometer",
            "torque_at_transmission", "accelerator_pedal_position",
            "fuel_consumed_since_restart"], function(key, i) {
        var data = trace[key];
        graphs[key] = drawTimeseries(trace, key, _.pluck(data, "timestamp"),
                _.pluck(data, "value"));
    });
}

<commit_msg>Revert "Draw max line horizontally - not sure I like this."<commit_after>var graphs = {};

var initDimensions = function(elementId) {
    // automatically size to the container using JQuery to get width/height
    width = $("#" + elementId).width();
    height = $("#" + elementId).height();

    // make sure to use offset() and not position() as we want it relative to
    // the document, not its parent
    xOffset = $("#" + elementId).offset().left;
    yOffset = $("#" + elementId).offset().top;
    return {width: width, height: height, xOffset: xOffset, yOffset: yOffset};
}

var drawTimeseries = function(trace, elementId, dataX, dataY) {
    // create an SVG element inside the element that fills 100% of the div
    var graph = d3.select("#" + elementId).append("svg:svg").attr("width", "100%")
            .attr("height", "100%");
    hoverContainer = $("#" + elementId + " svg");

    var dimensions = initDimensions(elementId);

    // X scale will fit values from 0-10 within range of pixels
    var x = d3.scale.linear().domain([_.min(dataX), _.max(dataX)]).range(
            [0, dimensions.width]);
    // Y scale will fit values from 0-10 within pixels 0-100
    var y = d3.scale.linear().domain([_.min(dataY), _.max(dataY)]).range(
            [dimensions.height, 0]);

    // create a line object that represents the SVG line we're creating
    var line = d3.svg.line()
    .x(function(d,i) {
        return x(d[0]);
    })
    .y(function(d) {
        return y(d[1]);
    })

    var hoverLineGroup = graph.append("svg:svg").attr("class", "hover-line");
    var hoverLine = hoverLineGroup.append("svg:line")
        .attr("x1", 10).attr("x2", 10)
        .attr("y1", 0).attr("y2", dimensions.height);
    hoverLine.classed("hide", true);

    var maxDataPoint = _.max(_.zip(dataX, dataY), function(point) {
        return point[1];
    });
    var maxPosition = x(maxDataPoint[0]);
    var maxLineGroup = graph.append("svg:svg").attr("class", "max-line");
    var maxLine = maxLineGroup.append("svg:line")
        .attr("x1", maxPosition).attr("x2", maxPosition)
        .attr("y1", 0).attr("y2", dimensions.height);

    var average = _.reduce(dataY, function(memo, value) { return memo + value; },
            0) / dataY.length;
    var averageLineGroup = graph.append("svg:svg").attr("class", "average-line");
    var averageLine = averageLineGroup.append("svg:line")
        .attr("x1", 0).attr("x2", dimensions.width)
        .attr("y1", y(average)).attr("y2", y(average));
    var averageText = averageLineGroup.append("svg:text")
        .attr("x", 5).attr("y", y(average) - 8)
        .attr("text-anchor", "left")
        .text("avg");

    // display the line by appending an svg:path element with the data line we created above
    graph.append("svg:path").attr("d", line(_.zip(dataX, dataY)));

    var graphHolder = {elementId: elementId, graph: graph, x: x, y: y,
            hoverLine: hoverLine, dimensions: dimensions, dataX: dataX,
            dataY: dataY};

    $(hoverContainer).mouseleave(function(event) {
        handleMouseOutGraph(event);
    });

    $(hoverContainer).mousemove(function(event) {
        handleMouseOverGraph(event, trace, graphHolder);
    });

    return graphHolder;
}

var timeseriesHoverHandler = {
    on: function(timestamp, trace, mouseX, mouseY) {
        _.each(graphs, function(otherGraph, i) {
            otherGraph.hoverLine.classed("hide", false);

            // set position of hoverLine
            otherGraph.hoverLine.attr("x1", mouseX).attr("x2", mouseX)

            var hoveredValue = findClosestToX(timestamp,
                otherGraph.dataX, otherGraph.dataY)[1];
            $("#current_" + otherGraph.elementId).text(hoveredValue.toFixed(2)).parent().show();
        });
    },
    off: function() {
        _.each(graphs, function(graph, i) {
            graph.hoverLine.classed("hide", true);
            $("#current_" + graph.elementId).parent().hide();
        });
    }
}

var drawTimeseriesGraphs = function(trace) {
    _.each(["vehicle_speed", "engine_speed", "odometer",
            "torque_at_transmission", "accelerator_pedal_position",
            "fuel_consumed_since_restart"], function(key, i) {
        var data = trace[key];
        graphs[key] = drawTimeseries(trace, key, _.pluck(data, "timestamp"),
                _.pluck(data, "value"));
    });
}

<|endoftext|>