<commit_before>{% load i18n %}
{% load inventree_extras %}

/*
 * Add a cached alert message to sesion storage
 */
function addCachedAlert(message, options={}) {

    var alerts = sessionStorage.getItem('inventree-alerts');

    if (alerts) {
        alerts = JSON.parse(alerts);
    } else {
        alerts = [];
    }

    alerts.push({
        message: message,
        style: options.style || 'success',
        icon: options.icon,
    });

    sessionStorage.setItem('inventree-alerts', JSON.stringify(alerts));
}

/*
 * Remove all cached alert messages
 */
function clearCachedAlerts() {
    sessionStorage.removeItem('inventree-alerts');
}

/*
 * Display an alert, or cache to display on reload
 */
function showAlertOrCache(message, cache, options={}) {

    if (cache) {
        addCachedAlert(message, options);
    } else {
        showMessage(message, options);
    }
}

/*
 * Display cached alert messages when loading a page
 */
function showCachedAlerts() {

    var alerts = JSON.parse(sessionStorage.getItem('inventree-alerts')) || [];

    alerts.forEach(function(alert) {
        showMessage(
            alert.message,
            {
                style: alert.style || 'success',
                icon: alert.icon,
            }
        );
    });

    clearCachedAlerts();
}

/*
 * Display an alert message at the top of the screen.
 * The message will contain a "close" button,
 * and also dismiss automatically after a certain amount of time.
 *
 * arguments:
 * - message: Text / HTML content to display
 *
 * options:
 * - style: alert style e.g. 'success' / 'warning'
 * - timeout: Time (in milliseconds) after which the message will be dismissed
 */
function showMessage(message, options={}) {

    var style = options.style || 'info';

    var timeout = options.timeout || 5000;

    var target = options.target || $('#alerts');

    var details = '';

    if (options.details) {
        details = `<p><small>${options.details}</p></small>`;
    }

    // Hacky function to get the next available ID
    var id = 1;

    while ($(`#alert-${id}`).exists()) {
        id++;
    }

    var icon = '';

    if (options.icon) {
        icon = `<span class='${options.icon}'></span>`;
    }

    // Construct the alert
    var html = `

        ${icon}
        ${message}
        ${details}
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>

    `;

    target.append(html);

    // Remove the alert automatically after a specified period of time
    $(`#alert-${id}`).delay(timeout).slideUp(200, function() {
        $(this).alert(close);
    });
}

var notificationWatcher = null;  // reference for the notificationWatcher
/**
 * start the regular notification checks
 **/
function startNotificationWatcher() {
    notificationCheck(force=true);
    notificationWatcher = setInterval(notificationCheck, 1000);
}

/**
 * stop the regular notification checks
 **/
function stopNotificationWatcher() {
    clearInterval(notificationWatcher);
}

var notificationUpdateTic = 0;
/**
 * The notification checker is initiated when the document is loaded. It checks if there are unread notifications
 * if unread messages exist the notification indicator is updated
 *
 * options:
 * - force: set true to force an update now (if you got in focus for example)
 **/
function notificationCheck(force = false) {
    notificationUpdateTic = notificationUpdateTic + 1;

    // refresh if forced or
    // if in focus and was not refreshed in the last 5 seconds
    if (force || (document.hasFocus() && notificationUpdateTic >= 5)) {
        notificationUpdateTic = 0;
        inventreeGet(
            '/api/notifications/',
            {
                read: false,
            },
            {
                success: function(response) {
                    updateNotificationIndicator(response.length);
                }
            }
        );
    }
}

/**
 * handles read / unread buttons and UI rebuilding
 *
 * arguments:
 * - btn: element that got clicked / fired the event -> must contain pk and target as attributes
 *
 * options:
 * - panel_caller: this button was clicked in the notification panel
 **/
function updateNotificationReadState(btn, panel_caller=false) {
    var url = `/api/notifications/${btn.attr('pk')}/${btn.attr('target')}/`;

    inventreePut(url, {}, {
    method: 'POST',
    success: function() {
        // update the notification tables if they were declared
        if (window.updateNotifications) {
            window.updateNotifications();
        }

        // update current notification count
        var count = parseInt($("#notification-counter").html());
        if (btn.attr('target') == 'read') {
            count = count - 1;
        } else {
            count = count + 1;
        }
        // update notification indicator now
        updateNotificationIndicator(count);

        // remove notification if called from notification panel
        if (panel_caller) {
            btn.parent().parent().remove()
        }
    }
    });
};

/**
 * Returns the html for a read / unread button
 *
 * arguments:
 * - pk: primary key of the notification
 * - state: current state of the notification (read / unread) -> just pass what you were handed by the api
 * - small: should the button be small
 **/
function getReadEditButton(pk, state, small=false) {
    if (state) {
        var bReadText = '{% trans "Mark as unread" %}';
        var bReadIcon = 'fas fa-bookmark icon-red';
        var bReadTarget = 'unread';
    } else {
        var bReadText = '{% trans "Mark as read" %}';
        var bReadIcon = 'far fa-bookmark icon-green';
        var bReadTarget = 'read';
    }

    var style = (small) ? 'btn-sm ' : '';
    return `<button title='${bReadText}' class='notification-read btn ${style}btn-outline-secondary' type='button' pk='${pk}' target='${bReadTarget}'><span class='${bReadIcon}'></span></button>`;
}

/**
 * fills the notification panel when opened
 **/
function openNotificationPanel() {
    var html = '';
    var center_ref = '#notification-center';

    inventreeGet(
        '/api/notifications/',
        {
            read: false,
        },
        {
            success: function(response) {
                if (response.length == 0) {
                    html = `<p class='text-muted'>{% trans "No unread notifications" %}</p>`;
                } else {
                    // build up items
                    response.forEach(function(item, index) {
                        html += '
';
                        // d-flex justify-content-between align-items-start
                        html += '
';
                        html += `<span class="badge rounded-pill bg-primary">${item.category}</span><span class="ms-2">${item.name}</span>`;
                        html += '
';
                        if (item.target) {
                            var link_text = `${item.target.model}: ${item.target.name}`;
                            if (item.target.link) {
                                link_text = `<a href='${item.target.link}'>${link_text}</a>`;
                            }
                            html += link_text
                        }
                        html += '
';
                        html += `<span class="text-muted">${item.age_human}</span>`;
                        html += getReadEditButton(item.pk, item.read, true);
                        html += "

";
                    });

                    // package up
                    html = `<ul class="list-group">${html}</ul>`
                }

                // set html
                $(center_ref).html(html);
            }
        }
    );

    $(center_ref).on('click', '.notification-read', function() {
        updateNotificationReadState($(this), true);
    });
}

/**
 * clears the notification panel when closed
 **/
function closeNotificationPanel() {
    $('#notification-center').html(`<p class='text-muted'>{% trans "Notifications will load here" %}</p>`);
}

/**
 * updates the notification counter
 **/
function updateNotificationIndicator(count) {
    // reset update Ticker -> safe some API bandwidth
    notificationUpdateTic = 0;

    if (count == 0) {
        $("#notification-alert").addClass("d-none");
    } else {
        $("#notification-alert").removeClass("d-none");
    }
    $("#notification-counter").html(count);
}
<commit_msg>style fix<commit_after>{% load i18n %}
{% load inventree_extras %}

/*
 * Add a cached alert message to sesion storage
 */
function addCachedAlert(message, options={}) {

    var alerts = sessionStorage.getItem('inventree-alerts');

    if (alerts) {
        alerts = JSON.parse(alerts);
    } else {
        alerts = [];
    }

    alerts.push({
        message: message,
        style: options.style || 'success',
        icon: options.icon,
    });

    sessionStorage.setItem('inventree-alerts', JSON.stringify(alerts));
}

/*
 * Remove all cached alert messages
 */
function clearCachedAlerts() {
    sessionStorage.removeItem('inventree-alerts');
}

/*
 * Display an alert, or cache to display on reload
 */
function showAlertOrCache(message, cache, options={}) {

    if (cache) {
        addCachedAlert(message, options);
    } else {
        showMessage(message, options);
    }
}

/*
 * Display cached alert messages when loading a page
 */
function showCachedAlerts() {

    var alerts = JSON.parse(sessionStorage.getItem('inventree-alerts')) || [];

    alerts.forEach(function(alert) {
        showMessage(
            alert.message,
            {
                style: alert.style || 'success',
                icon: alert.icon,
            }
        );
    });

    clearCachedAlerts();
}

/*
 * Display an alert message at the top of the screen.
 * The message will contain a "close" button,
 * and also dismiss automatically after a certain amount of time.
 *
 * arguments:
 * - message: Text / HTML content to display
 *
 * options:
 * - style: alert style e.g. 'success' / 'warning'
 * - timeout: Time (in milliseconds) after which the message will be dismissed
 */
function showMessage(message, options={}) {

    var style = options.style || 'info';

    var timeout = options.timeout || 5000;

    var target = options.target || $('#alerts');

    var details = '';

    if (options.details) {
        details = `<p><small>${options.details}</p></small>`;
    }

    // Hacky function to get the next available ID
    var id = 1;

    while ($(`#alert-${id}`).exists()) {
        id++;
    }

    var icon = '';

    if (options.icon) {
        icon = `<span class='${options.icon}'></span>`;
    }

    // Construct the alert
    var html = `

        ${icon}
        ${message}
        ${details}
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>

    `;

    target.append(html);

    // Remove the alert automatically after a specified period of time
    $(`#alert-${id}`).delay(timeout).slideUp(200, function() {
        $(this).alert(close);
    });
}

var notificationWatcher = null;  // reference for the notificationWatcher
/**
 * start the regular notification checks
 **/
function startNotificationWatcher() {
    notificationCheck(force=true);
    notificationWatcher = setInterval(notificationCheck, 1000);
}

/**
 * stop the regular notification checks
 **/
function stopNotificationWatcher() {
    clearInterval(notificationWatcher);
}

var notificationUpdateTic = 0;
/**
 * The notification checker is initiated when the document is loaded. It checks if there are unread notifications
 * if unread messages exist the notification indicator is updated
 *
 * options:
 * - force: set true to force an update now (if you got in focus for example)
 **/
function notificationCheck(force = false) {
    notificationUpdateTic = notificationUpdateTic + 1;

    // refresh if forced or
    // if in focus and was not refreshed in the last 5 seconds
    if (force || (document.hasFocus() && notificationUpdateTic >= 5)) {
        notificationUpdateTic = 0;
        inventreeGet(
            '/api/notifications/',
            {
                read: false,
            },
            {
                success: function(response) {
                    updateNotificationIndicator(response.length);
                }
            }
        );
    }
}

/**
 * handles read / unread buttons and UI rebuilding
 *
 * arguments:
 * - btn: element that got clicked / fired the event -> must contain pk and target as attributes
 *
 * options:
 * - panel_caller: this button was clicked in the notification panel
 **/
function updateNotificationReadState(btn, panel_caller=false) {
    var url = `/api/notifications/${btn.attr('pk')}/${btn.attr('target')}/`;

    inventreePut(url, {}, {
        method: 'POST',
        success: function() {
            // update the notification tables if they were declared
            if (window.updateNotifications) {
                window.updateNotifications();
            }

            // update current notification count
            var count = parseInt($('#notification-counter').html());
            if (btn.attr('target') == 'read') {
                count = count - 1;
            } else {
                count = count + 1;
            }
            // update notification indicator now
            updateNotificationIndicator(count);

            // remove notification if called from notification panel
            if (panel_caller) {
                btn.parent().parent().remove();
            }
        }
    });
};

/**
 * Returns the html for a read / unread button
 *
 * arguments:
 * - pk: primary key of the notification
 * - state: current state of the notification (read / unread) -> just pass what you were handed by the api
 * - small: should the button be small
 **/
function getReadEditButton(pk, state, small=false) {
    if (state) {
        var bReadText = '{% trans "Mark as unread" %}';
        var bReadIcon = 'fas fa-bookmark icon-red';
        var bReadTarget = 'unread';
    } else {
        var bReadText = '{% trans "Mark as read" %}';
        var bReadIcon = 'far fa-bookmark icon-green';
        var bReadTarget = 'read';
    }

    var style = (small) ? 'btn-sm ' : '';
    return `<button title='${bReadText}' class='notification-read btn ${style}btn-outline-secondary' type='button' pk='${pk}' target='${bReadTarget}'><span class='${bReadIcon}'></span></button>`;
}

/**
 * fills the notification panel when opened
 **/
function openNotificationPanel() {
    var html = '';
    var center_ref = '#notification-center';

    inventreeGet(
        '/api/notifications/',
        {
            read: false,
        },
        {
            success: function(response) {
                if (response.length == 0) {
                    html = `<p class='text-muted'>{% trans "No unread notifications" %}</p>`;
                } else {
                    // build up items
                    response.forEach(function(item, index) {
                        html += '
';
                        // d-flex justify-content-between align-items-start
                        html += '
';
                        html += `<span class="badge rounded-pill bg-primary">${item.category}</span><span class="ms-2">${item.name}</span>`;
                        html += '
';
                        if (item.target) {
                            var link_text = `${item.target.model}: ${item.target.name}`;
                            if (item.target.link) {
                                link_text = `<a href='${item.target.link}'>${link_text}</a>`;
                            }
                            html += link_text;
                        }
                        html += '
';
                        html += `<span class="text-muted">${item.age_human}</span>`;
                        html += getReadEditButton(item.pk, item.read, true);
                        html += '

';
                    });

                    // package up
                    html = `<ul class="list-group">${html}</ul>`;
                }

                // set html
                $(center_ref).html(html);
            }
        }
    );

    $(center_ref).on('click', '.notification-read', function() {
        updateNotificationReadState($(this), true);
    });
}

/**
 * clears the notification panel when closed
 **/
function closeNotificationPanel() {
    $('#notification-center').html(`<p class='text-muted'>{% trans "Notifications will load here" %}</p>`);
}

/**
 * updates the notification counter
 **/
function updateNotificationIndicator(count) {
    // reset update Ticker -> safe some API bandwidth
    notificationUpdateTic = 0;

    if (count == 0) {
        $('#notification-alert').addClass('d-none');
    } else {
        $('#notification-alert').removeClass('d-none');
    }
    $('#notification-counter').html(count);
}
<|endoftext|>


<commit_before>import 'aframe';
import 'aframe-animation-component';
import 'aframe-text-component';
import { Entity, Scene } from 'aframe-react';
import React from 'react';

import Camera from './Camera';
import Text from './Text';
import Sky from './Sky';
import Image from './Image';
import Dome from './Dome';

const testImages = [
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg',
  'https://s3-us-west-2.amazonaws.com/s.cdpn.io/336999/me.jpg'
];

class PhodomeScene extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'red',
      images: testImages
    };
  }

  changeColor() {
    const colors = ['red', 'orange', 'yellow', 'green', 'blue'];
    this.setState({
      color: colors[Math.floor(Math.random() * colors.length)]
    });
  }

  render () {
    return (
      <Scene>
        <Camera>
          <a-cursor
            animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150">
          </a-cursor>
        </Camera>

        <Sky color="#000"/>

        <Dome images={this.state.images} />

        <Entity light={{type: 'ambient', color: '#888'}}/>
        <Entity light={{type: 'directional', intensity: 0.5}} position='-1 1 0'/>
        <Entity light={{type: 'directional', intensity: 1}} position='1 1 0'/>

      </Scene>
    );
  }
}

export default PhodomeScene;
<commit_msg>(cleanup) Clean out unnecessary code from PhodomeScene<commit_after>import 'aframe';
import 'aframe-animation-component';
import 'aframe-text-component';
import { Entity, Scene } from 'aframe-react';
import React from 'react';
import axios from 'axios';

import Camera from './Camera';
import Text from './Text';
import Sky from './Sky';
import Image from './Image';
import Dome from './Dome';

class PhodomeScene extends React.Component {
  constructor() {
    super();
    this.state = {
      images: []
    };
  }

  componentDidMount() {
    // fetch from /api/images using axios
  }

  render () {
    return (
      <Scene>
        <Camera>
          <a-cursor
            animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150">
          </a-cursor>
        </Camera>

        <Sky color="#000"/>

        <Dome images={this.state.images} />

        <Entity light={{type: 'ambient', color: '#888'}}/>
        <Entity light={{type: 'directional', intensity: 0.5}} position='-1 1 0'/>
        <Entity light={{type: 'directional', intensity: 1}} position='1 1 0'/>

      </Scene>
    );
  }
}

export default PhodomeScene;
<|endoftext|>


<commit_before>/**
 * Legend module.
 *
 * @return singleton instance of the legend class (extends Widget).
 */
define([
  'underscore',
  'handlebars',
  'map/presenters/LegendPresenter',
  'text!map/templates/legend/legend.handlebars',
  'text!map/templates/legend/biomass_loss.handlebars',
  'text!map/templates/legend/biomass.handlebars',
  'text!map/templates/legend/imazon.handlebars',
  'text!map/templates/legend/fires.handlebars',
  'text!map/templates/legend/forest2000.handlebars',
  'text!map/templates/legend/pantropical.handlebars',
  'text!map/templates/legend/idnPrimary.handlebars',
  'text!map/templates/legend/intact2013.handlebars',
  'text!map/templates/legend/grump.handlebars',
  'text!map/templates/legend/stories.handlebars',
  'text!map/templates/legend/terra_i.handlebars',
  'text!map/templates/legend/concesiones_forestales.handlebars',
  'text!map/templates/legend/concesiones_forestalesType.handlebars',
  'text!map/templates/legend/hondurasForest.handlebars',
  'text!map/templates/legend/colombiaForestChange.handlebars',
  'text!map/templates/legend/tigers.handlebars',
  'text!map/templates/legend/dam_hotspots.handlebars',
  'text!map/templates/legend/us_land_cover.handlebars',
  'text!map/templates/legend/global_land_cover.handlebars',
  'text!map/templates/legend/forma.handlebars',
  'text!map/templates/legend/bra_biomes.handlebars',
  'text!map/templates/legend/idn_peat.handlebars',
  'text!map/templates/legend/hsdw.handlebars',
  'text!map/templates/legend/plantations_by_type.handlebars',
  'text!map/templates/legend/plantations_by_species.handlebars',
  'text!map/templates/legend/peatland_drainage.handlebars',
  'text!map/templates/legend/colombiaForestChange.handlebars',
  'text!map/templates/legend/us_land_cover.handlebars',
  'text!map/templates/legend/bra_biomes.handlebars',
  'text!map/templates/legend/gtm_forest_change.handlebars',
  'text!map/templates/legend/gtm_forest_cover.handlebars',
  'text!map/templates/legend/gtm_forest_density.handlebars',
  'text!map/templates/legend/khm_eco_land_conc.handlebars',
  'text!map/templates/legend/usa_forest_ownership.handlebars',
  'text!map/templates/legend/mysPA.handlebars',
  'text!map/templates/legend/per_mining.handlebars',
  'text!map/templates/legend/raisg_mining.handlebars',

], function(_, Handlebars, Presenter, tpl, biomass_lossTpl, biomassTpl, imazonTpl, firesTpl,
    forest2000Tpl, pantropicalTpl, idnPrimaryTpl, intact2013Tpl, grumpTpl, storiesTpl, terra_iTpl, concesionesTpl, concesionesTypeTpl, hondurasForestTPL,colombiaForestChangeTPL, tigersTPL, dam_hotspotsTPL, us_land_coverTPL, global_land_coverTPL, formaTPL,bra_biomesTPL, idn_peatTPL,hsdwTPL, gfwPlantationByTypeTpl, gfwPlantationBySpeciesTpl,peatland_drainageTpl,colombiaForestChangeTpl, us_land_coverTpl, bra_biomesTpl, gtm_forest_changeTpl, gtm_forest_coverTpl, gtm_forest_densityTpl, khm_eco_land_concTpl, usa_forest_ownershipTpl, mysPATpl, per_miningTpl,raisg_miningTpl) {

  'use strict';

  var LegendModel = Backbone.Model.extend({
    defaults:{
      hidden: true,
      categories_status: [],
    }
  });

  var LegendView = Backbone.View.extend({

    el: '#module-legend',

    template: Handlebars.compile(tpl),

    /**
     * Optional layers detail templates.
     */
    detailsTemplates: {
      biomass_loss: Handlebars.compile(biomass_lossTpl),
      carbon_stocks: Handlebars.compile(biomassTpl),
      imazon: Handlebars.compile(imazonTpl),
      fires: Handlebars.compile(firesTpl),
      forest2000: Handlebars.compile(forest2000Tpl),
      pantropical: Handlebars.compile(pantropicalTpl),
      idn_primary: Handlebars.compile(idnPrimaryTpl),
      ifl_2013_deg: Handlebars.compile(intact2013Tpl),
      grump2000: Handlebars.compile(grumpTpl),
      user_stories:  Handlebars.compile(storiesTpl),
      terrailoss: Handlebars.compile(terra_iTpl),
      concesiones_forestales: Handlebars.compile(concesionesTpl),
      concesiones_forestalesNS: Handlebars.compile(concesionesTypeTpl),
      WMSLayer: Handlebars.compile(hondurasForestTPL),
      colombia_forest_change: Handlebars.compile(colombiaForestChangeTPL),
      tigers: Handlebars.compile(tigersTPL),
      dam_hotspots: Handlebars.compile(dam_hotspotsTPL),
      us_land_cover: Handlebars.compile(us_land_coverTPL),
      global_land_cover : Handlebars.compile(global_land_coverTPL),
      us_land_cover_change : Handlebars.compile(us_land_coverTPL),
      forma : Handlebars.compile(formaTPL),
      bra_biomes : Handlebars.compile(bra_biomesTPL),
      idn_peat_lands : Handlebars.compile(idn_peatTPL),
      hwsd : Handlebars.compile(hsdwTPL),
      plantations_by_type: Handlebars.compile(gfwPlantationByTypeTpl),
      plantations_by_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      peatland_drainage: Handlebars.compile(peatland_drainageTpl),
      idn_peatland_drainage: Handlebars.compile(peatland_drainageTpl),
      colombia_forest_change: Handlebars.compile(colombiaForestChangeTPL),
      us_land_cover: Handlebars.compile(us_land_coverTPL),
      us_land_cover_change : Handlebars.compile(us_land_coverTPL),
      bra_biomes : Handlebars.compile(bra_biomesTPL),
      bra_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      per_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      lbr_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      col_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      khm_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      idn_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      mys_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      bra_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      per_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      lbr_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      col_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      khm_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      idn_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      mys_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      gtm_forest_change1: Handlebars.compile(gtm_forest_changeTpl),
      gtm_forest_change2: Handlebars.compile(gtm_forest_changeTpl),
      gtm_forest_cover: Handlebars.compile(gtm_forest_coverTpl),
      gtm_forest_density: Handlebars.compile(gtm_forest_densityTpl),
      khm_eco_land_conc: Handlebars.compile(khm_eco_land_concTpl),
      usa_forest_ownership: Handlebars.compile(usa_forest_ownershipTpl),
      mys_protected_areas:Handlebars.compile(mysPATpl),
      bra_mining:Handlebars.compile(raisg_miningTpl),
      per_mining:Handlebars.compile(per_miningTpl),

    },

    options: {
      hidden: true
    },

    events: {
      'click .category-name' : '_toogleCategory',
      'click .layer-sublayer': '_toggleLayer',
      'click .canopy-button' : '_showCanopy',
      'click .layer-close'   : '_removeLayer',
      'click .close' : 'toogleLegend',
      'click #title-dialog-legend' : 'toogleEmbedLegend',
      'click .toggle-title' : 'toggleLegendOptions',
      'change input'        : 'updateRange'
    },

    initialize: function() {
      _.bindAll(this, 'update');
      this.presenter = new Presenter(this);
      this.model = new LegendModel();
      this.embed = $('body').hasClass('is-embed-action');
      this.$el.removeClass('hide');
      this.setListeners();
    },

    setListeners: function(){
      this.model.on('change:hidden', this.toogleModule, this);
    },

    toogleModule: function(){
      this.$el.toggleClass('hide', this.model.get('hidden'));
    },

    toogleEmbedLegend: function(e){
      e && e.preventDefault();
      var active = this.$titleDialog.hasClass('active');
      this.$titleDialog.toggleClass('active', !active);
      this.$categories.toggleClass('active', !active);
      this.$buttonLegendBox.toggleClass('active', !active);

    },

    openGFW: function(){
      if (this.embed && !!this.$linkLegendBox) {
        var href = window.location.href.replace('/embed','');
        this.$linkLegendBox.attr('href', href);
      }
    },

    /**
     *
     * @param  {array}  categories layers ordered by category
     * @param  {object} options    legend options
     */
    _renderLegend: function(categories, options, geographic) {
      var iso = null;
      var layersGlobal = [];
      var layersIso = [];
      var categoriesGlobal = [];
      var categoriesIso = [];
      var layers = _.flatten(categories);
      var layersLength = layers.length;

      // Append details template to layer.
      _.each(layers, function(layer) {
        layer.source = (layer.slug === 'nothing') ? null : layer.slug;
        if (this.detailsTemplates[layer.slug]) {
          layer.detailsTpl = this.detailsTemplates[layer.slug]({
            threshold: options.threshold || 30,
            layerTitle: layer.title,
            minrange: options.minrange || '0',
            maxrange: options.maxrange || '917'
          });
        }
        if (layer.iso) {
          var countries = amplify.store('countries');
          iso = layer.iso;
          layersIso.push(layer);
          layer.category_status = layer.category_slug+'-iso';
        } else {
          layersGlobal.push(layer);
          layer.category_status = layer.category_slug+'-global'
        }
        layer.geographic = geographic ? 'checked' : '';
      }, this);

      categoriesGlobal = this.statusCategories(_.groupBy(layersGlobal, function(layer){ return layer.category_slug }));
      categoriesIso = this.statusCategories(_.groupBy(layersIso, function(layer){ return layer.category_slug }));

      if (iso) {
        var country = _.find(amplify.store('countries'), _.bind(function(country){
          return country.iso === iso;
        }, this ));
      }
      var name = (country) ? country.name : iso;

      var html = this.template({
        categories: (jQuery.isEmptyObject(categoriesGlobal)) ? false : categoriesGlobal,
        categoriesIso: categoriesIso,
        layersLength: layersLength,
        iso: iso,
        name: name
      });

      this.render(html);
    },

    statusCategories: function(array){
      // Search for layer 'nothing'
      var categories_status = this.model.get('categories_status');
      _.each(array, function(category) {
        for (var i = 0; i< category.length; i++) {
          // Mantain categories closed in rendering
          (categories_status.indexOf(category[i]['category_status']) != -1) ? category['closed'] = true : category['closed'] = false;
          // Get layer's length of each category
          category['layers_length'] = i + 1;
        }
      }, this);

      return array;
    },

    toogleLegend: function(bool){
      var to = (bool && bool.currentTarget) ? false : bool;
      this.$el.toggleClass('active', to);
      this.presenter.toggleOverlay(to);
    },

    /**
     * Toggle selected sublayers on the legend widget.
     *
     * @param  {object} layers The layers object
     */
    toggleSelected: function(layers) {
      _.each(this.$el.find('.layer-sublayer'), function(div) {
        var $div = $(div);
        var $toggle = $div.find('.onoffswitch');
        var layer = layers[$div.data('sublayer')];

        if (layer) {
          $toggle.addClass('checked');
          $toggle.css('background', layer.category_color);
        } else {
          $toggle.removeClass('checked').css('background', '');
        }
      }, this);
    },

    render: function(html) {
      this.$el.html(html);
      this.$titleDialog = $('#title-dialog-legend');
      this.$categories = this.$el.find('.categories');
      this.$buttonLegendBox =  $('#button-box-embed-legend');
      this.$linkLegendBox =  $('#link-embed-legend');
    },

    /**
     * Set widget from layers object.
     *
     * @param  {array} layers
     */
    update: function(categories, options, geographic) {
      if (categories.length === 0) {
        this.model.set('hidden', true);
      } else {
        this.model.set({'hidden': false, 'boxClosed': false});
        this._renderLegend(categories, options, geographic);
      }
      //Experiment
      this.presenter.initExperiment('source');
    },

    /**
     * Handles a toggle layer change UI event by dispatching
     * to LegendPresenter.
     *
     * @param  {event} event Click event
     */
    _toggleLayer: function(event) {
      var layerSlug = $(event.currentTarget).data('sublayer');
      this.presenter.toggleLayer(layerSlug);
    },

    _toogleCategory: function(e){
      if ($(window).width() > window.gfw.config.GFW_MOBILE) {
        // Save category status in an array
        var categories_status = this.model.get('categories_status');
        var slug = $(e.currentTarget).data('category_slug');
        var index = categories_status.indexOf(slug);
        (index != -1) ? categories_status.splice(index, 1) : categories_status.push(slug);
        this.model.set('categories_status',categories_status);

        $(e.currentTarget).parent().toggleClass('closed');
        $(e.currentTarget).parent().children('.layers').toggleClass('closed');
      }
    },

    _removeLayer: function(e){
      e && e.preventDefault();
      var layerSlug = $(e.currentTarget).data('slug');
      this.presenter.toggleLayer(layerSlug);
    },

    _showCanopy: function(e){
      if (!! e.target.parentNode.classList.contains('minavgmax')) return this._getUncertainty(e);
      if (!! e.target.parentNode.classList.contains('range'))     return;
      e && e.preventDefault();
      this.presenter.showCanopy();
    },

    _getUncertainty: function(e) {
      this.presenter.changeUncertainty(e.target.dataset);
    },

    _setUncertaintyOptionUI: function(type) {
      var $opt = this.$el.find('[data-quantity="'+type+'"]');
      $opt.addClass('current').siblings('.current').removeClass('current');
    },
    toggleLegendOptions: function(e) {
      $(e.target).find('span').toggleClass('active');
      $(e.target).siblings('.toggle-legend-option').toggle('250');
    },
    updateRange: function(e) {
      var newrange = this.$el.find('input');
      var targets = this.$el.find('.labels em');

      newrange = [newrange[0].value,newrange[1].value];
      targets.first().html(newrange[0]);
      targets.last().html(newrange[1]);
      this.presenter.setNewRange([newrange[0],newrange[1]]);
    }

  });

  return LegendView;
});
<commit_msg>validate user input<commit_after>/**
 * Legend module.
 *
 * @return singleton instance of the legend class (extends Widget).
 */
define([
  'underscore',
  'handlebars',
  'map/presenters/LegendPresenter',
  'text!map/templates/legend/legend.handlebars',
  'text!map/templates/legend/biomass_loss.handlebars',
  'text!map/templates/legend/biomass.handlebars',
  'text!map/templates/legend/imazon.handlebars',
  'text!map/templates/legend/fires.handlebars',
  'text!map/templates/legend/forest2000.handlebars',
  'text!map/templates/legend/pantropical.handlebars',
  'text!map/templates/legend/idnPrimary.handlebars',
  'text!map/templates/legend/intact2013.handlebars',
  'text!map/templates/legend/grump.handlebars',
  'text!map/templates/legend/stories.handlebars',
  'text!map/templates/legend/terra_i.handlebars',
  'text!map/templates/legend/concesiones_forestales.handlebars',
  'text!map/templates/legend/concesiones_forestalesType.handlebars',
  'text!map/templates/legend/hondurasForest.handlebars',
  'text!map/templates/legend/colombiaForestChange.handlebars',
  'text!map/templates/legend/tigers.handlebars',
  'text!map/templates/legend/dam_hotspots.handlebars',
  'text!map/templates/legend/us_land_cover.handlebars',
  'text!map/templates/legend/global_land_cover.handlebars',
  'text!map/templates/legend/forma.handlebars',
  'text!map/templates/legend/bra_biomes.handlebars',
  'text!map/templates/legend/idn_peat.handlebars',
  'text!map/templates/legend/hsdw.handlebars',
  'text!map/templates/legend/plantations_by_type.handlebars',
  'text!map/templates/legend/plantations_by_species.handlebars',
  'text!map/templates/legend/peatland_drainage.handlebars',
  'text!map/templates/legend/colombiaForestChange.handlebars',
  'text!map/templates/legend/us_land_cover.handlebars',
  'text!map/templates/legend/bra_biomes.handlebars',
  'text!map/templates/legend/gtm_forest_change.handlebars',
  'text!map/templates/legend/gtm_forest_cover.handlebars',
  'text!map/templates/legend/gtm_forest_density.handlebars',
  'text!map/templates/legend/khm_eco_land_conc.handlebars',
  'text!map/templates/legend/usa_forest_ownership.handlebars',
  'text!map/templates/legend/mysPA.handlebars',
  'text!map/templates/legend/per_mining.handlebars',
  'text!map/templates/legend/raisg_mining.handlebars',

], function(_, Handlebars, Presenter, tpl, biomass_lossTpl, biomassTpl, imazonTpl, firesTpl,
    forest2000Tpl, pantropicalTpl, idnPrimaryTpl, intact2013Tpl, grumpTpl, storiesTpl, terra_iTpl, concesionesTpl, concesionesTypeTpl, hondurasForestTPL,colombiaForestChangeTPL, tigersTPL, dam_hotspotsTPL, us_land_coverTPL, global_land_coverTPL, formaTPL,bra_biomesTPL, idn_peatTPL,hsdwTPL, gfwPlantationByTypeTpl, gfwPlantationBySpeciesTpl,peatland_drainageTpl,colombiaForestChangeTpl, us_land_coverTpl, bra_biomesTpl, gtm_forest_changeTpl, gtm_forest_coverTpl, gtm_forest_densityTpl, khm_eco_land_concTpl, usa_forest_ownershipTpl, mysPATpl, per_miningTpl,raisg_miningTpl) {

  'use strict';

  var LegendModel = Backbone.Model.extend({
    defaults:{
      hidden: true,
      categories_status: [],
    }
  });

  var LegendView = Backbone.View.extend({

    el: '#module-legend',

    template: Handlebars.compile(tpl),

    /**
     * Optional layers detail templates.
     */
    detailsTemplates: {
      biomass_loss: Handlebars.compile(biomass_lossTpl),
      carbon_stocks: Handlebars.compile(biomassTpl),
      imazon: Handlebars.compile(imazonTpl),
      fires: Handlebars.compile(firesTpl),
      forest2000: Handlebars.compile(forest2000Tpl),
      pantropical: Handlebars.compile(pantropicalTpl),
      idn_primary: Handlebars.compile(idnPrimaryTpl),
      ifl_2013_deg: Handlebars.compile(intact2013Tpl),
      grump2000: Handlebars.compile(grumpTpl),
      user_stories:  Handlebars.compile(storiesTpl),
      terrailoss: Handlebars.compile(terra_iTpl),
      concesiones_forestales: Handlebars.compile(concesionesTpl),
      concesiones_forestalesNS: Handlebars.compile(concesionesTypeTpl),
      WMSLayer: Handlebars.compile(hondurasForestTPL),
      colombia_forest_change: Handlebars.compile(colombiaForestChangeTPL),
      tigers: Handlebars.compile(tigersTPL),
      dam_hotspots: Handlebars.compile(dam_hotspotsTPL),
      us_land_cover: Handlebars.compile(us_land_coverTPL),
      global_land_cover : Handlebars.compile(global_land_coverTPL),
      us_land_cover_change : Handlebars.compile(us_land_coverTPL),
      forma : Handlebars.compile(formaTPL),
      bra_biomes : Handlebars.compile(bra_biomesTPL),
      idn_peat_lands : Handlebars.compile(idn_peatTPL),
      hwsd : Handlebars.compile(hsdwTPL),
      plantations_by_type: Handlebars.compile(gfwPlantationByTypeTpl),
      plantations_by_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      peatland_drainage: Handlebars.compile(peatland_drainageTpl),
      idn_peatland_drainage: Handlebars.compile(peatland_drainageTpl),
      colombia_forest_change: Handlebars.compile(colombiaForestChangeTPL),
      us_land_cover: Handlebars.compile(us_land_coverTPL),
      us_land_cover_change : Handlebars.compile(us_land_coverTPL),
      bra_biomes : Handlebars.compile(bra_biomesTPL),
      bra_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      per_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      lbr_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      col_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      khm_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      idn_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      mys_plantations_type: Handlebars.compile(gfwPlantationByTypeTpl),
      bra_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      per_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      lbr_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      col_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      khm_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      idn_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      mys_plantations_species: Handlebars.compile(gfwPlantationBySpeciesTpl),
      gtm_forest_change1: Handlebars.compile(gtm_forest_changeTpl),
      gtm_forest_change2: Handlebars.compile(gtm_forest_changeTpl),
      gtm_forest_cover: Handlebars.compile(gtm_forest_coverTpl),
      gtm_forest_density: Handlebars.compile(gtm_forest_densityTpl),
      khm_eco_land_conc: Handlebars.compile(khm_eco_land_concTpl),
      usa_forest_ownership: Handlebars.compile(usa_forest_ownershipTpl),
      mys_protected_areas:Handlebars.compile(mysPATpl),
      bra_mining:Handlebars.compile(raisg_miningTpl),
      per_mining:Handlebars.compile(per_miningTpl),

    },

    options: {
      hidden: true
    },

    events: {
      'click .category-name' : '_toogleCategory',
      'click .layer-sublayer': '_toggleLayer',
      'click .canopy-button' : '_showCanopy',
      'click .layer-close'   : '_removeLayer',
      'click .close' : 'toogleLegend',
      'click #title-dialog-legend' : 'toogleEmbedLegend',
      'click .toggle-title' : 'toggleLegendOptions',
      'change input'        : 'updateRange'
    },

    initialize: function() {
      _.bindAll(this, 'update');
      this.presenter = new Presenter(this);
      this.model = new LegendModel();
      this.embed = $('body').hasClass('is-embed-action');
      this.$el.removeClass('hide');
      this.setListeners();
    },

    setListeners: function(){
      this.model.on('change:hidden', this.toogleModule, this);
    },

    toogleModule: function(){
      this.$el.toggleClass('hide', this.model.get('hidden'));
    },

    toogleEmbedLegend: function(e){
      e && e.preventDefault();
      var active = this.$titleDialog.hasClass('active');
      this.$titleDialog.toggleClass('active', !active);
      this.$categories.toggleClass('active', !active);
      this.$buttonLegendBox.toggleClass('active', !active);

    },

    openGFW: function(){
      if (this.embed && !!this.$linkLegendBox) {
        var href = window.location.href.replace('/embed','');
        this.$linkLegendBox.attr('href', href);
      }
    },

    /**
     *
     * @param  {array}  categories layers ordered by category
     * @param  {object} options    legend options
     */
    _renderLegend: function(categories, options, geographic) {
      var iso = null;
      var layersGlobal = [];
      var layersIso = [];
      var categoriesGlobal = [];
      var categoriesIso = [];
      var layers = _.flatten(categories);
      var layersLength = layers.length;

      // Append details template to layer.
      _.each(layers, function(layer) {
        layer.source = (layer.slug === 'nothing') ? null : layer.slug;
        if (this.detailsTemplates[layer.slug]) {
          layer.detailsTpl = this.detailsTemplates[layer.slug]({
            threshold: options.threshold || 30,
            layerTitle: layer.title,
            minrange: options.minrange || '0',
            maxrange: options.maxrange || '917'
          });
        }
        if (layer.iso) {
          var countries = amplify.store('countries');
          iso = layer.iso;
          layersIso.push(layer);
          layer.category_status = layer.category_slug+'-iso';
        } else {
          layersGlobal.push(layer);
          layer.category_status = layer.category_slug+'-global'
        }
        layer.geographic = geographic ? 'checked' : '';
      }, this);

      categoriesGlobal = this.statusCategories(_.groupBy(layersGlobal, function(layer){ return layer.category_slug }));
      categoriesIso = this.statusCategories(_.groupBy(layersIso, function(layer){ return layer.category_slug }));

      if (iso) {
        var country = _.find(amplify.store('countries'), _.bind(function(country){
          return country.iso === iso;
        }, this ));
      }
      var name = (country) ? country.name : iso;

      var html = this.template({
        categories: (jQuery.isEmptyObject(categoriesGlobal)) ? false : categoriesGlobal,
        categoriesIso: categoriesIso,
        layersLength: layersLength,
        iso: iso,
        name: name
      });

      this.render(html);
    },

    statusCategories: function(array){
      // Search for layer 'nothing'
      var categories_status = this.model.get('categories_status');
      _.each(array, function(category) {
        for (var i = 0; i< category.length; i++) {
          // Mantain categories closed in rendering
          (categories_status.indexOf(category[i]['category_status']) != -1) ? category['closed'] = true : category['closed'] = false;
          // Get layer's length of each category
          category['layers_length'] = i + 1;
        }
      }, this);

      return array;
    },

    toogleLegend: function(bool){
      var to = (bool && bool.currentTarget) ? false : bool;
      this.$el.toggleClass('active', to);
      this.presenter.toggleOverlay(to);
    },

    /**
     * Toggle selected sublayers on the legend widget.
     *
     * @param  {object} layers The layers object
     */
    toggleSelected: function(layers) {
      _.each(this.$el.find('.layer-sublayer'), function(div) {
        var $div = $(div);
        var $toggle = $div.find('.onoffswitch');
        var layer = layers[$div.data('sublayer')];

        if (layer) {
          $toggle.addClass('checked');
          $toggle.css('background', layer.category_color);
        } else {
          $toggle.removeClass('checked').css('background', '');
        }
      }, this);
    },

    render: function(html) {
      this.$el.html(html);
      this.$titleDialog = $('#title-dialog-legend');
      this.$categories = this.$el.find('.categories');
      this.$buttonLegendBox =  $('#button-box-embed-legend');
      this.$linkLegendBox =  $('#link-embed-legend');
    },

    /**
     * Set widget from layers object.
     *
     * @param  {array} layers
     */
    update: function(categories, options, geographic) {
      if (categories.length === 0) {
        this.model.set('hidden', true);
      } else {
        this.model.set({'hidden': false, 'boxClosed': false});
        this._renderLegend(categories, options, geographic);
      }
      //Experiment
      this.presenter.initExperiment('source');
    },

    /**
     * Handles a toggle layer change UI event by dispatching
     * to LegendPresenter.
     *
     * @param  {event} event Click event
     */
    _toggleLayer: function(event) {
      var layerSlug = $(event.currentTarget).data('sublayer');
      this.presenter.toggleLayer(layerSlug);
    },

    _toogleCategory: function(e){
      if ($(window).width() > window.gfw.config.GFW_MOBILE) {
        // Save category status in an array
        var categories_status = this.model.get('categories_status');
        var slug = $(e.currentTarget).data('category_slug');
        var index = categories_status.indexOf(slug);
        (index != -1) ? categories_status.splice(index, 1) : categories_status.push(slug);
        this.model.set('categories_status',categories_status);

        $(e.currentTarget).parent().toggleClass('closed');
        $(e.currentTarget).parent().children('.layers').toggleClass('closed');
      }
    },

    _removeLayer: function(e){
      e && e.preventDefault();
      var layerSlug = $(e.currentTarget).data('slug');
      this.presenter.toggleLayer(layerSlug);
    },

    _showCanopy: function(e){
      if (!! e.target.parentNode.classList.contains('minavgmax')) return this._getUncertainty(e);
      if (!! e.target.parentNode.classList.contains('range'))     return;
      e && e.preventDefault();
      this.presenter.showCanopy();
    },

    _getUncertainty: function(e) {
      this.presenter.changeUncertainty(e.target.dataset);
    },

    _setUncertaintyOptionUI: function(type) {
      var $opt = this.$el.find('[data-quantity="'+type+'"]');
      $opt.addClass('current').siblings('.current').removeClass('current');
    },
    toggleLegendOptions: function(e) {
      $(e.target).find('span').toggleClass('active');
      $(e.target).siblings('.toggle-legend-option').toggle('250');
    },
    updateRange: function(e) {
      var newrange = this.$el.find('input');
      var targets = this.$el.find('.labels em');
      newrange = [newrange[0].value,newrange[1].value];
      if (~~newrange[0] < 0) return this.resetRanges('min');
      if (~~newrange[1] > 917) return this.resetRanges('max');
      targets.first().html(newrange[0]);
      targets.last().html(newrange[1]);
      this.presenter.setNewRange([newrange[0],newrange[1]]);
    },
    resetRanges: function(end) {
      var newrange = this.$el.find('input');
      var targets = this.$el.find('.labels em');
      if (end === 'min'){
        newrange[0].value = 0;
        targets.first().html('0');
      }
      if (end === 'max'){
        newrange[1].value = 917;
        targets.last().html('917');
      }
    }

  });

  return LegendView;
});
<|endoftext|>


<commit_before>var transcript = null;
var sdviewer = null;
var formatter = null;
var hsplitL, hsplitR;
var cmdstack = null;
var spellcheck = null;
var taskwatcher = null;

$(function() {
    // setup toolbar
    $("#link_viewers").button({
        text: false,
        icons: {
            primary: "ui-icon-link",
        },
    });
    $("#spellcheck").button();
    $("#format").buttonset();
    $("#next_page").button({
        text: false,
        icons: {
            primary: "ui-icon-seek-next",
        },
    });
    $("#prev_page").button({
        disabled: true,
        text: false,
        icons: {
            primary: "ui-icon-seek-prev",
        },
    });
    $("#save_data").button({
        disabled: true,
        text: false,
        icons: {
            primary: "ui-icon-disk",
        },
    });
    $("#edit_task").button({
        text: false,
        icons: {
            primary: "ui-icon-wrench",
        },
    });
    $("#heading").button({
        disabled: true,
        text: true,
    });

    $("#image_zoomin").click(function(event) {
        sdviewer.viewport.zoomIn(2);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-zoomin",
        }
    });
    $("#image_zoomout").click(function(event) {
        sdviewer.viewport.zoomOut(0.5);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-zoomout",
        }
    });
    $("#centre").click(function(event) {
        sdviewer.goHome();
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-home",
        }
    });
    $("#fullscreen").click(function(event) {
        sdviewer.setFullPage(true);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-arrow-4-diag",
        }
    });

    $("#refresh").click(function(event) {
        sdviewer.refresh();
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-refresh",
        }
    });
    $("#undo_command").button({
        text: false,
        disabled: true,
        icons: {
            primary: "ui-icon-arrowreturnthick-1-w",
        }
    });
    $("#redo_command").button({
        text: false,
        disabled: true,
        icons: {
            primary: "ui-icon-arrowreturnthick-1-e",
        }
    });

    $("#vlink").buttonset();

    $("#format_block").click(function(event) {
        formatter.blockLayout($("#transcript"));
    });
    $("#format_column").click(function(event) {
        formatter.columnLayout($("#transcript"));
    });
    $("#undo_command").click(function(event) {
        cmdstack.undo();
    });
    $("#redo_command").click(function(event) {
        cmdstack.redo();
    });

    // map of key commands to functions
    var cmdmap = {
        "ctrl+z": function() {
            cmdstack.undo();
        },
        "ctrl+shift+z": function() {
            cmdstack.redo();
        },
        "ctrl+shift+s": function() {
            $("#spellcheck").click();
        },
        "alt+ctrl+s": function() {
            saveTranscript();
        },
        "tab": function() {
            transcript.forward();
        },
        "shift+tab": function() {
            transcript.backward();
        },
        "f2": function() {
            transcript.editLine();
        },
    };

    var editcmdmap = {
        "esc": function(element, content) {
            transcript.finishEditing(element, content, false);
        },
        "return": function(element, content) {
            transcript.finishEditing(element, content, true);
        },
        "shift+tab": function(element, content) {
            transcript.finishEditing(element, content, true);
            transcript.backward();
            transcript.editLine();
        },
        "tab": function(element, content) {
            transcript.finishEditing(element, content, true);
            transcript.forward();
            transcript.editLine();
        },
    };

    function bindEditKeys(element, initialcontent) {
        unbindEditKeys();
        unbindNavKeys();
        $.each(editcmdmap, function(key, handler) {
            $(document).bind("keydown.editkeycmd", key, function(event) {
                handler(element, initialcontent);
                event.stopPropagation();
                event.preventDefault();
            });
        });
        $(element).bind("blur.editkeycmd", function(event) {
            transcript.finishEditing(element, initialcontent, true, true);
        });
    }

    function bindNavKeys() {
        unbindEditKeys();
        unbindNavKeys();
        $.each(cmdmap, function(key, handler) {
            $(document).bind("keydown.keycmd", key, function(event) {
                handler.apply();
                event.stopPropagation();
                event.preventDefault();
            });
        });
    }

    function unbindNavKeys() {
        $(document).unbind(".keycmd");
    }

    function unbindEditKeys(element) {
        $(document).unbind(".editkeycmd");
        $(element).unbind(".editkeycmd");
    }

    function saveState() {
        var view = {
            follow: $("input[name='vlink']:checked").attr("id"),
            format: $("input[name='format']:checked").attr("id"),
        };
        $.cookie("transcript_view", JSON.stringify(view));
    }

    function loadState() {
        var viewcookie = $.cookie("transcript_view");
        if (viewcookie) {
            var view = JSON.parse(viewcookie);
            $("#" + view.follow).prop("checked", true).button("refresh");
            $("#" + view.format).prop("checked", true).button("refresh");
        }
    }

    function unsavedPrompt() {
        return confirm("Save changes to transcript?");
    }

    function getPid() {
        return $("#id_pid").val();
    }

    function updateTask(event) {
        $("#transcript").load("/documents/transcript/" + getPid() + "/",
                null, function(text) {
                    transcript.setWaiting(false);
                    transcript.refresh();
                    pageLoaded();
        });
    }

    function updateNavButtons() {
        $("#heading").button({disabled: true});
    }

    function positionViewer(position) {
        // ensure the given line is centred in the viewport
        //sdviewer.setBufferOverlays({
        //    "current": [position],
        //});
        if ($("#link_viewers").prop("checked")) {
            sdviewer.fitBounds(position.dilate(20), true);
            sdviewer.clearHighlights();
            sdviewer.addHighlight(position);
            sdviewer.update();
        }
    }

    function pageLoaded() {
        // get should-be-hidden implementation details
        // i.e. the task id that process the page.  We
        // want to rebinarize with the same params
        var task_pid = getPid();
        $("#edit_task").attr("href",
                "/presets/builder/" + task_pid + "?ref="
                + encodeURIComponent(window.location.href.replace(window.location.origin, "")));

        taskwatcher.run("/documents/binary/" + task_pid + "/");
    }

    function stackChanged() {
        $("#undo_command")
            .text(cmdstack.undoText())
            .button({disabled: !cmdstack.canUndo()})
            .button("refresh");
        $("#redo_command")
            .text(cmdstack.redoText())
            .button({disabled: !cmdstack.canRedo()})
            .button("refresh");
        $("#save_data").button({
            disabled: !cmdstack.canUndo(),
        });
    }

    taskwatcher = new OcrJs.TaskWatcher(300); // millisecond delay
    taskwatcher.addListeners({
        start: function() {
            sdviewer.setWaiting(true);
        },
        poll: function(count) {

        },
        error: function(msg) {
            alert(msg);
        },
        done: function(data) {
            sdviewer.setWaiting(false);
            $(sdviewer).data("binpath", data.results.out);
            sdviewer.openDzi(data.results.dst);
            sdviewer.setWaiting(false);
        },
    });

    // initialize undo stack
    cmdstack = new OcrJs.UndoStack(this, {max: 50});

    cmdstack.addListeners({
        undoStateChanged: stackChanged,
        redoStateChanged: stackChanged,
        indexChanged: stackChanged,
        stateChanged: function() {
        },
    });

    // initialise the transcript editor
    //transcript = new OcrJs.TranscriptEditor(document.getElementById("transcript"));
    transcript = new OcrJs.HocrEditor.Editor($("#transcript").get(0), cmdstack);

    function showPluginPane(onoff) {
        hsplitL[onoff ? "show" : "hide"]("south");
    }

    // initialize spellcheck
    spellcheck = new OcrJs.Spellchecker($("#plugin"), cmdstack);
    spellcheck.addListeners({
        onWordCorrection: function() {
        },
        onWordHighlight: function(element) {
            transcript.setCurrentLine($(element).closest(".ocr_line"));
        },
    });

    // When a page loads, read the data and request the source
    // image is rebinarized so we can view it in the viewer
    // This is likely to be horribly inefficient, at least
    // at first...
    transcript.addListeners({
        hoverPosition: function(position) {
            if (!($("input[name=vlink]:checked").val() == "hover"
                    && sdviewer.isReady()))
            return;
            positionViewer(position);
        },
        clickPosition: function(position) {
            if (!($("input[name=vlink]:checked").val() == "click"
                        && sdviewer.isReady()))
                return;
            positionViewer(position);
        },
        startEditing: function(element) {
            unbindNavKeys();
            bindEditKeys(element, $(element).html());
        },
        stopEditing: function(element, content) {
            unbindEditKeys(element);
            bindNavKeys();
        },
    });

    $("#spellcheck").change(function(event) {
        if ($(this).prop("checked")) {
            showPluginPane(true);
            spellcheck.spellcheck($(".ocr_line"));
        } else {
            spellcheck.unhighlight($(".ocr_line"));
            showPluginPane(false);
        }
    });

    function saveTranscript(fun, funargs) {
        $.ajax({
            url: "/ocr/save/" + getPid() + "/",
            data: {
                data: transcript.getData()
            },
            dataType: "json",
            type: "POST",
            error: OcrJs.ajaxErrorHandler,
            success: function(data) {
                if (data && data.ok) {
                    $("#save_data").button({
                        disabled: true,
                    });
                    if (fun)
                        fun.apply(this, funargs);
                } else {
                    alert(data);
                }
            },
        });
    };

    $("#save_data").click(function(event) {
        saveTranscript();
    });

    $("#save_training_data").click(function(event) {
        var pid = getPid();
        $.ajax({
            url: "/reference_pages/create_from_task/" + pid + "/",
            dataType: "json",
            type: "POST",
            success: function(data) {
                if (data.error)
                    return alert("Error: " + data.error);
                alert("Saved!");
            },
            complete: function() {
            },
            error: OcrJs.ajaxErrorHandler,
        });
    });

    $("#prev_page").click(function(event) {
    });

    $("#next_page").click(function(event) {
    });

    // line formatter object
    formatter = new OcrJs.LineFormatter();

    // viewer object
    sdviewer = new DziViewer.Viewer($("#viewer").get(0), {
        numBuffers: 1,
        height: 300,
        dashboard: false,
    });

    updateTask();
    updateNavButtons();
    window.addEventListener("hashchange", updateTask);

    hsplitL = $("#maincontent").layout({
        applyDefaultStyles: true,
        north: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
        },
        south: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
            initClosed: true,
        },
    });

    hsplitR = $("#sidebar").layout({
        applyDefaultStyles: true,
        north: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
        },
    });

    hsplitL.options.center.onresize_end = function() {
        setTimeout(function() {
            sdviewer.resetSize();
            transcript.resetSize();
            $("input[name=format]:checked").click();
        });
    };
    hsplitR.options.center.onresize_end = function() {
        setTimeout(function() {
            sdviewer.resetSize();
            transcript.resetSize();
            $("input[name=format]:checked").click();
        });
    };

    $(window).unload(function() {
        saveState();
    });

    $(window).resize();
    sdviewer.resetSize();

    // set up key commands
    bindNavKeys();

    loadState();
});

<commit_msg>Change save URL (yes, need to fix this...)<commit_after>var transcript = null;
var sdviewer = null;
var formatter = null;
var hsplitL, hsplitR;
var cmdstack = null;
var spellcheck = null;
var taskwatcher = null;

$(function() {
    // setup toolbar
    $("#link_viewers").button({
        text: false,
        icons: {
            primary: "ui-icon-link",
        },
    });
    $("#spellcheck").button();
    $("#format").buttonset();
    $("#next_page").button({
        text: false,
        icons: {
            primary: "ui-icon-seek-next",
        },
    });
    $("#prev_page").button({
        disabled: true,
        text: false,
        icons: {
            primary: "ui-icon-seek-prev",
        },
    });
    $("#save_data").button({
        disabled: true,
        text: false,
        icons: {
            primary: "ui-icon-disk",
        },
    });
    $("#edit_task").button({
        text: false,
        icons: {
            primary: "ui-icon-wrench",
        },
    });
    $("#heading").button({
        disabled: true,
        text: true,
    });

    $("#image_zoomin").click(function(event) {
        sdviewer.viewport.zoomIn(2);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-zoomin",
        }
    });
    $("#image_zoomout").click(function(event) {
        sdviewer.viewport.zoomOut(0.5);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-zoomout",
        }
    });
    $("#centre").click(function(event) {
        sdviewer.goHome();
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-home",
        }
    });
    $("#fullscreen").click(function(event) {
        sdviewer.setFullPage(true);
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-arrow-4-diag",
        }
    });

    $("#refresh").click(function(event) {
        sdviewer.refresh();
    }).button({
        text: false,
        icons: {
            primary: "ui-icon-refresh",
        }
    });
    $("#undo_command").button({
        text: false,
        disabled: true,
        icons: {
            primary: "ui-icon-arrowreturnthick-1-w",
        }
    });
    $("#redo_command").button({
        text: false,
        disabled: true,
        icons: {
            primary: "ui-icon-arrowreturnthick-1-e",
        }
    });

    $("#vlink").buttonset();

    $("#format_block").click(function(event) {
        formatter.blockLayout($("#transcript"));
    });
    $("#format_column").click(function(event) {
        formatter.columnLayout($("#transcript"));
    });
    $("#undo_command").click(function(event) {
        cmdstack.undo();
    });
    $("#redo_command").click(function(event) {
        cmdstack.redo();
    });

    // map of key commands to functions
    var cmdmap = {
        "ctrl+z": function() {
            cmdstack.undo();
        },
        "ctrl+shift+z": function() {
            cmdstack.redo();
        },
        "ctrl+shift+s": function() {
            $("#spellcheck").click();
        },
        "alt+ctrl+s": function() {
            saveTranscript();
        },
        "tab": function() {
            transcript.forward();
        },
        "shift+tab": function() {
            transcript.backward();
        },
        "f2": function() {
            transcript.editLine();
        },
    };

    var editcmdmap = {
        "esc": function(element, content) {
            transcript.finishEditing(element, content, false);
        },
        "return": function(element, content) {
            transcript.finishEditing(element, content, true);
        },
        "shift+tab": function(element, content) {
            transcript.finishEditing(element, content, true);
            transcript.backward();
            transcript.editLine();
        },
        "tab": function(element, content) {
            transcript.finishEditing(element, content, true);
            transcript.forward();
            transcript.editLine();
        },
    };

    function bindEditKeys(element, initialcontent) {
        unbindEditKeys();
        unbindNavKeys();
        $.each(editcmdmap, function(key, handler) {
            $(document).bind("keydown.editkeycmd", key, function(event) {
                handler(element, initialcontent);
                event.stopPropagation();
                event.preventDefault();
            });
        });
        $(element).bind("blur.editkeycmd", function(event) {
            transcript.finishEditing(element, initialcontent, true, true);
        });
    }

    function bindNavKeys() {
        unbindEditKeys();
        unbindNavKeys();
        $.each(cmdmap, function(key, handler) {
            $(document).bind("keydown.keycmd", key, function(event) {
                handler.apply();
                event.stopPropagation();
                event.preventDefault();
            });
        });
    }

    function unbindNavKeys() {
        $(document).unbind(".keycmd");
    }

    function unbindEditKeys(element) {
        $(document).unbind(".editkeycmd");
        $(element).unbind(".editkeycmd");
    }

    function saveState() {
        var view = {
            follow: $("input[name='vlink']:checked").attr("id"),
            format: $("input[name='format']:checked").attr("id"),
        };
        $.cookie("transcript_view", JSON.stringify(view));
    }

    function loadState() {
        var viewcookie = $.cookie("transcript_view");
        if (viewcookie) {
            var view = JSON.parse(viewcookie);
            $("#" + view.follow).prop("checked", true).button("refresh");
            $("#" + view.format).prop("checked", true).button("refresh");
        }
    }

    function unsavedPrompt() {
        return confirm("Save changes to transcript?");
    }

    function getPid() {
        return $("#id_pid").val();
    }

    function updateTask(event) {
        $("#transcript").load("/documents/transcript/" + getPid() + "/",
                null, function(text) {
                    transcript.setWaiting(false);
                    transcript.refresh();
                    pageLoaded();
        });
    }

    function updateNavButtons() {
        $("#heading").button({disabled: true});
    }

    function positionViewer(position) {
        // ensure the given line is centred in the viewport
        //sdviewer.setBufferOverlays({
        //    "current": [position],
        //});
        if ($("#link_viewers").prop("checked")) {
            sdviewer.fitBounds(position.dilate(20), true);
            sdviewer.clearHighlights();
            sdviewer.addHighlight(position);
            sdviewer.update();
        }
    }

    function pageLoaded() {
        // get should-be-hidden implementation details
        // i.e. the task id that process the page.  We
        // want to rebinarize with the same params
        var task_pid = getPid();
        $("#edit_task").attr("href",
                "/presets/builder/" + task_pid + "?ref="
                + encodeURIComponent(window.location.href.replace(window.location.origin, "")));

        taskwatcher.run("/documents/binary/" + task_pid + "/");
    }

    function stackChanged() {
        $("#undo_command")
            .text(cmdstack.undoText())
            .button({disabled: !cmdstack.canUndo()})
            .button("refresh");
        $("#redo_command")
            .text(cmdstack.redoText())
            .button({disabled: !cmdstack.canRedo()})
            .button("refresh");
        $("#save_data").button({
            disabled: !cmdstack.canUndo(),
        });
    }

    taskwatcher = new OcrJs.TaskWatcher(300); // millisecond delay
    taskwatcher.addListeners({
        start: function() {
            sdviewer.setWaiting(true);
        },
        poll: function(count) {

        },
        error: function(msg) {
            alert(msg);
        },
        done: function(data) {
            sdviewer.setWaiting(false);
            $(sdviewer).data("binpath", data.results.out);
            sdviewer.openDzi(data.results.dst);
            sdviewer.setWaiting(false);
        },
    });

    // initialize undo stack
    cmdstack = new OcrJs.UndoStack(this, {max: 50});

    cmdstack.addListeners({
        undoStateChanged: stackChanged,
        redoStateChanged: stackChanged,
        indexChanged: stackChanged,
        stateChanged: function() {
        },
    });

    // initialise the transcript editor
    //transcript = new OcrJs.TranscriptEditor(document.getElementById("transcript"));
    transcript = new OcrJs.HocrEditor.Editor($("#transcript").get(0), cmdstack);

    function showPluginPane(onoff) {
        hsplitL[onoff ? "show" : "hide"]("south");
    }

    // initialize spellcheck
    spellcheck = new OcrJs.Spellchecker($("#plugin"), cmdstack);
    spellcheck.addListeners({
        onWordCorrection: function() {
        },
        onWordHighlight: function(element) {
            transcript.setCurrentLine($(element).closest(".ocr_line"));
        },
    });

    // When a page loads, read the data and request the source
    // image is rebinarized so we can view it in the viewer
    // This is likely to be horribly inefficient, at least
    // at first...
    transcript.addListeners({
        hoverPosition: function(position) {
            if (!($("input[name=vlink]:checked").val() == "hover"
                    && sdviewer.isReady()))
            return;
            positionViewer(position);
        },
        clickPosition: function(position) {
            if (!($("input[name=vlink]:checked").val() == "click"
                        && sdviewer.isReady()))
                return;
            positionViewer(position);
        },
        startEditing: function(element) {
            unbindNavKeys();
            bindEditKeys(element, $(element).html());
        },
        stopEditing: function(element, content) {
            unbindEditKeys(element);
            bindNavKeys();
        },
    });

    $("#spellcheck").change(function(event) {
        if ($(this).prop("checked")) {
            showPluginPane(true);
            spellcheck.spellcheck($(".ocr_line"));
        } else {
            spellcheck.unhighlight($(".ocr_line"));
            showPluginPane(false);
        }
    });

    function saveTranscript(fun, funargs) {
        $.ajax({
            url: "/documents/save_transcript/" + getPid() + "/",
            data: {
                data: transcript.getData()
            },
            dataType: "json",
            type: "POST",
            error: OcrJs.ajaxErrorHandler,
            success: function(data) {
                if (data && data.ok) {
                    $("#save_data").button({
                        disabled: true,
                    });
                    if (fun)
                        fun.apply(this, funargs);
                } else {
                    alert(data);
                }
            },
        });
    };

    $("#save_data").click(function(event) {
        saveTranscript();
    });

    $("#save_training_data").click(function(event) {
        var pid = getPid();
        $.ajax({
            url: "/reference_pages/create_from_task/" + pid + "/",
            dataType: "json",
            type: "POST",
            success: function(data) {
                if (data.error)
                    return alert("Error: " + data.error);
                alert("Saved!");
            },
            complete: function() {
            },
            error: OcrJs.ajaxErrorHandler,
        });
    });

    $("#prev_page").click(function(event) {
    });

    $("#next_page").click(function(event) {
    });

    // line formatter object
    formatter = new OcrJs.LineFormatter();

    // viewer object
    sdviewer = new DziViewer.Viewer($("#viewer").get(0), {
        numBuffers: 1,
        height: 300,
        dashboard: false,
    });

    updateTask();
    updateNavButtons();
    window.addEventListener("hashchange", updateTask);

    hsplitL = $("#maincontent").layout({
        applyDefaultStyles: true,
        north: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
        },
        south: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
            initClosed: true,
        },
    });

    hsplitR = $("#sidebar").layout({
        applyDefaultStyles: true,
        north: {
            resizable: false,
            closable: false,
            slidable: false,
            spacing_open: 0,
        },
    });

    hsplitL.options.center.onresize_end = function() {
        setTimeout(function() {
            sdviewer.resetSize();
            transcript.resetSize();
            $("input[name=format]:checked").click();
        });
    };
    hsplitR.options.center.onresize_end = function() {
        setTimeout(function() {
            sdviewer.resetSize();
            transcript.resetSize();
            $("input[name=format]:checked").click();
        });
    };

    $(window).unload(function() {
        saveState();
    });

    $(window).resize();
    sdviewer.resetSize();

    // set up key commands
    bindNavKeys();

    loadState();
});

<|endoftext|>


<commit_before>Meteor.publish('allPosts', function () {
  "use strict";
  var result = Posts.find({}, {
    limit: 50
  });
  return result;
});

Meteor.publish('recentPosts', function (start) {
  "use strict";
  return Posts.find({
    createdAt: {
      $gte: start
    }
  },{
    sort: {
      createdAt: -1
    },
    limit: 50
  });
});

Meteor.publish('bestPosts', function (start) {
  "use strict";
  return Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 50
  });
});

Meteor.publish('hotPosts', function (start) {
  "use strict";
  var allArr = Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 10000
  }).fetch();

  var hotTable = {};

  console.log('Sorting the ' + allArr.length + ' hottest posts');

  _(allArr).forEach(function (post) {
    var secondsAgo = Math.abs((new Date()) - (new Date(post.createdAt))) / 1000;
    var hoursAgo = secondsAgo / 60;
    var points = (post.oldPoints - 1);
    var decay = Math.pow(hoursAgo + 2, 1.5);
    hotTable[post._id] = points / decay;
  });

  var sortObject = function (obj) {
    var arr = [];
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        arr.push({
          'key': prop,
          'value': obj[prop]
        });
      }
    }
    arr.sort(function(a, b) { return b.value - a.value; });
    return arr; // returns array
  };

  var sorted = sortObject(hotTable);

  // delete all of the old data and insert the new stuff
  Hot.remove({}, function (err) {
    if (err) {
      throw err;
    } else {
      _.forEach(sorted, function (el) {
        Meteor.bindEnvironment(function() {
          Hot.insert(Posts.findOne({_id: el.key}));
        })();
      });
    }
  });

  return Hot.find();
});

Meteor.publish('randomPosts', function (start) {
  "use strict";
  return Posts.find({
    createdAt: {$gte: start}
  },{
    limit: 50,
    skip: 10
  });
});
<commit_msg>Limit hot sorting to 50 posts<commit_after>Meteor.publish('allPosts', function () {
  "use strict";
  var result = Posts.find({}, {
    limit: 50
  });
  return result;
});

Meteor.publish('recentPosts', function (start) {
  "use strict";
  return Posts.find({
    createdAt: {
      $gte: start
    }
  },{
    sort: {
      createdAt: -1
    },
    limit: 50
  });
});

Meteor.publish('bestPosts', function (start) {
  "use strict";
  return Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 50
  });
});

Meteor.publish('hotPosts', function (start) {
  "use strict";
  var allArr = Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 10000
  }).fetch();

  var hotTable = {};

  console.log('Sorting the ' + allArr.length + ' hottest posts');

  _(allArr).forEach(function (post) {
    var secondsAgo = Math.abs((new Date()) - (new Date(post.createdAt))) / 1000;
    var hoursAgo = secondsAgo / 60;
    var points = (post.oldPoints - 1);
    var decay = Math.pow(hoursAgo + 2, 1.5);
    hotTable[post._id] = points / decay;
  });

  var sortObject = function (obj) {
    var arr = [];
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        arr.push({
          'key': prop,
          'value': obj[prop]
        });
      }
    }
    arr.sort(function(a, b) { return b.value - a.value; });
    return arr; // returns array
  };

  var sorted = sortObject(hotTable);

  // delete all of the old data and insert the new stuff
  Hot.remove({}, function (err) {
    if (err) {
      throw err;
    } else {
      _.forEach(sorted, function (el) {
        Meteor.bindEnvironment(function() {
          Hot.insert(Posts.findOne({_id: el.key}));
        })();
      });
    }
  });

  return Hot.find(
    {},
    {
      limit: 50
    }
  );
});

Meteor.publish('randomPosts', function (start) {
  "use strict";
  return Posts.find({
    createdAt: {$gte: start}
  },{
    limit: 50,
    skip: 10
  });
});
<|endoftext|>


<commit_before>lichess.movetimeChart = function(data) {
  var log1p = Math.log1p || function(x) { return Math.log(x + 1); };

  lichess.loadScript('/assets/javascripts/chart/common.js').done(function() {
    lichess.loadScript('/assets/javascripts/chart/division.js').done(function() {
      lichess.chartCommon('highchart').done(function() {
        lichess.movetimeChart.render = function() {
          $('#movetimes_chart:not(.rendered)').each(function() {
            var $this = $(this).addClass('rendered');

            var series = {
              white: [],
              black: []
            };

            var tree = data.treeParts;
            var moveCentis = data.game.moveCentis ||
                 data.game.moveTimes.map(function(i) { return i * 10; });
            var ply = 0;
            var max = 0;

            moveCentis.forEach(function(time, i) {
              var node = tree[i + 1];
              ply = node ? node.ply : ply + 1;
              var san = node ? node.san : '-';

              var turn = (ply + 1) >> 1;
              var color = ply & 1;
              var y = Math.pow(log1p(.005 * Math.min(time, 6e4)), 2);
              max = Math.max(y, max);

              series[color ? 'white' : 'black'].push({
                name: turn + (color ? '. ' : '... ') + san,
                x: i,
                y: color ? y : -y
              });
            });

            var disabled = {
              enabled: false
            };
            var noText = {
              text: null
            };
            $this.highcharts({
              credits: disabled,
              legend: disabled,
              series: [{
                name: 'White',
                data: series.white
              }, {
                name: 'Black',
                data: series.black
              }],
              chart: {
                type: 'area',
                spacing: [2, 0, 2, 0],
                animation: false
              },
              tooltip: {
                formatter: function() {
                  var seconds = moveCentis[this.x] / 100;
                  if (seconds) seconds = seconds.toFixed(seconds >= 2 ? 1 : 2);
                  return this.point.name + '
' + seconds + ' seconds';
                }
              },
              plotOptions: {
                series: {
                  animation: false
                },
                area: {
                  fillColor: Highcharts.theme.lichess.area.white,
                  negativeFillColor: Highcharts.theme.lichess.area.black,
                  fillOpacity: 1,
                  threshold: 0,
                  lineWidth: 1,
                  color: '#3893E8',
                  allowPointSelect: true,
                  cursor: 'pointer',
                  states: {
                    hover: {
                      lineWidth: 1
                    }
                  },
                  events: {
                    click: function(event) {
                      if (event.point) {
                        event.point.select();
                        lichess.analyse.jumpToIndex(event.point.x);
                      }
                    }
                  },
                  marker: {
                    radius: 1,
                    states: {
                      hover: {
                        radius: 3,
                        lineColor: '#3893E8',
                        fillColor: '#ffffff'
                      },
                      select: {
                        radius: 4,
                        lineColor: '#3893E8',
                        fillColor: '#ffffff'
                      }
                    }
                  }
                }
              },
              title: noText,
              xAxis: {
                title: noText,
                labels: disabled,
                lineWidth: 0,
                tickWidth: 0,
                plotLines: lichess.divisionLines(data.game.division)
              },
              yAxis: {
                title: noText,
                min: -max,
                max: max,
                labels: disabled,
                gridLineWidth: 0
              }
            });
          });
          lichess.analyse.onChange();
        };
        lichess.movetimeChart.render();
      });
    });
  });
};
<commit_msg>Update movetime scaling<commit_after>lichess.movetimeChart = function(data) {
  var log1p = Math.log1p || function(x) { return Math.log(x + 1); };

  lichess.loadScript('/assets/javascripts/chart/common.js').done(function() {
    lichess.loadScript('/assets/javascripts/chart/division.js').done(function() {
      lichess.chartCommon('highchart').done(function() {
        lichess.movetimeChart.render = function() {
          $('#movetimes_chart:not(.rendered)').each(function() {
            var $this = $(this).addClass('rendered');

            var series = {
              white: [],
              black: []
            };

            var tree = data.treeParts;
            var moveCentis = data.game.moveCentis ||
                 data.game.moveTimes.map(function(i) { return i * 10; });
            var ply = 0;
            var max = 0;

            moveCentis.forEach(function(time, i) {
              var node = tree[i + 1];
              ply = node ? node.ply : ply + 1;
              var san = node ? node.san : '-';

              var turn = (ply + 1) >> 1;
              var color = ply & 1;
              var y = Math.pow(log1p(.003 * Math.min(time, 12e4)), 2);
              max = Math.max(y, max);

              series[color ? 'white' : 'black'].push({
                name: turn + (color ? '. ' : '... ') + san,
                x: i,
                y: color ? y : -y
              });
            });

            var disabled = {
              enabled: false
            };
            var noText = {
              text: null
            };
            $this.highcharts({
              credits: disabled,
              legend: disabled,
              series: [{
                name: 'White',
                data: series.white
              }, {
                name: 'Black',
                data: series.black
              }],
              chart: {
                type: 'area',
                spacing: [2, 0, 2, 0],
                animation: false
              },
              tooltip: {
                formatter: function() {
                  var seconds = moveCentis[this.x] / 100;
                  if (seconds) seconds = seconds.toFixed(seconds >= 2 ? 1 : 2);
                  return this.point.name + '
' + seconds + ' seconds';
                }
              },
              plotOptions: {
                series: {
                  animation: false
                },
                area: {
                  fillColor: Highcharts.theme.lichess.area.white,
                  negativeFillColor: Highcharts.theme.lichess.area.black,
                  fillOpacity: 1,
                  threshold: 0,
                  lineWidth: 1,
                  color: '#3893E8',
                  allowPointSelect: true,
                  cursor: 'pointer',
                  states: {
                    hover: {
                      lineWidth: 1
                    }
                  },
                  events: {
                    click: function(event) {
                      if (event.point) {
                        event.point.select();
                        lichess.analyse.jumpToIndex(event.point.x);
                      }
                    }
                  },
                  marker: {
                    radius: 1,
                    states: {
                      hover: {
                        radius: 3,
                        lineColor: '#3893E8',
                        fillColor: '#ffffff'
                      },
                      select: {
                        radius: 4,
                        lineColor: '#3893E8',
                        fillColor: '#ffffff'
                      }
                    }
                  }
                }
              },
              title: noText,
              xAxis: {
                title: noText,
                labels: disabled,
                lineWidth: 0,
                tickWidth: 0,
                plotLines: lichess.divisionLines(data.game.division)
              },
              yAxis: {
                title: noText,
                min: -max,
                max: max,
                labels: disabled,
                gridLineWidth: 0
              }
            });
          });
          lichess.analyse.onChange();
        };
        lichess.movetimeChart.render();
      });
    });
  });
};
<|endoftext|>