<commit_before>/*****************************************************************************
 * inteface.js
 * ===========
 * Classes and functions relating to the media player interface.
 *****************************************************************************/

/* Classes
 **********/

/*************************************
 TrackListControl
 ----------------
 Specialized version of a ListViewControl made to display media items -
 specifically, playlists. May be subclassed, e.g. the queue makes use of
 a subclass of this to add queue control functionality.
 *************************************/
function TrackListControl() {
    ListViewControl.call(this);
    var headers = ["Title"];
    this.changeHeader(headers);
    // clearTracks will reset things to a default state
    this.clearTracks();
}
    TrackListControl.prototype = new ListViewControl();
    // clearPlaylist() is like clear(), but also sets the playlist to an empty one
    TrackListControl.prototype.clearTracks = function() {
        this.setTracks([]);
    }
    TrackListControl.prototype.setTracks = function( tracks ) {
        this.tracks = tracks;
        //TODO: Probably better to set up the row information then call parent's _render
        this._render();
    }
    TrackListControl.prototype.appendTrack = function(track) {
        this.tracks.push(track);
        this.appendRow(track.title, track);
    }
    // Returns of list of selected track IDs
    TrackListControl.prototype.getSelectedTracks = function() {
        // First get selected row indexes
        var selected = this.getSelected();
        // Then get track IDs from it
        var tracks = new Array();
        for (i in selected) {
            tracks.push(this.rows[selected[i]].extra);
        }
        return tracks;
    }
    // Extends base class to also remove the item from the track list
    TrackListControl.prototype.deleteItem = function(index) {
        this.tracks.splice(index, 1);
        ListViewControl.prototype.deleteItem.call(this, index);
    }
    // Private methods --------------
    // Recreates every row
    TrackListControl.prototype._render = function() {
        this.clear();
        for (var tracknum in this.tracks) {
            var trackTitle = this.tracks[tracknum].title;
            this.appendRow(trackTitle, this.tracks[tracknum]);
        }
    }

/*************************************
 QueueControl
 ------------
 Definition for the Queue class, which manages the current playlist.
 The queue is basically a specialized subclass of a TrackListControl
 that adds methods for controlling the player and playlist management.
 *************************************/
function QueueControl() {
    TrackListControl.call(this);
    this.currentlyPlaying = null;   // null == nothing playing
    // Events
    page.audio.addEventListener("ended", this.trackFinished, false);
    this.listElement.addEventListener("rowclick", function(e) {
        // Subtract one here to correct for the header row
        e.listControl.playItem(e.row.rowIndex-1);
    }, false);
    // Stick it in the DOM
    document.getElementById("queueContainer").appendChild(this.listElement);
}
    QueueControl.prototype = new TrackListControl();
    QueueControl.prototype.clearPlaylist = function() {
        this.setPlaylist(new Playlist());
    }
    QueueControl.prototype.setPlaylist = function( playlist ) {
        this.playlist = playlist;
        this.setTracks(playlist.items);
    }
    QueueControl.prototype.playItem = function( trackIndex ) {
        var track = this.playlist.items[trackIndex];
        page.audio.src = track.url;
        // TODO: more detailed metadata display
        page.meta.innerHTML = track.title;
        // Start playing
        page.audio.play();
        // Update currently playing highlight
        this.highlightRow(parseInt(trackIndex));
        this.currentlyPlaying = parseInt(trackIndex);
    }
    // Event handlers -----------
    QueueControl.prototype.trackFinished = function(e) {
        if (queue.currentlyPlaying < queue.tracks.length-1) {
            //TODO: vary behavior depending on options (autoplay off, shuffle, etc.)
            queue.playItem(queue.currentlyPlaying + 1);
        }
    }

function Playlist(items, name) {
    if (items == undefined) {
        items = [];
    }
    if (name == undefined) {
        name = "<Unnamed>";
    }
    this.items = items;
    this.name = name;
}

/* Functions
 ************/

// Helper function that gets called at page load and builds a LUT for DOM elements
function bindElementList() {
    list = new Object();

    list.queue =   document.getElementById("queuePane");
    list.sidebar = document.getElementById("sidebarPane");
    list.library = document.getElementById("libraryPane");
    list.audio =   document.getElementById("audioPlayer");
    list.meta =    document.getElementById("metadata");

    // Place it in the global namespace for easy access
    window.page = list;
}
<commit_msg>Fix the queue's default playlist not being defaulted<commit_after>/*****************************************************************************
 * inteface.js
 * ===========
 * Classes and functions relating to the media player interface.
 *****************************************************************************/

/* Classes
 **********/

/*************************************
 TrackListControl
 ----------------
 Specialized version of a ListViewControl made to display media items -
 specifically, playlists. May be subclassed, e.g. the queue makes use of
 a subclass of this to add queue control functionality.
 *************************************/
function TrackListControl() {
    ListViewControl.call(this);
    var headers = ["Title"];
    this.changeHeader(headers);
    // clearTracks will reset things to a default state
    this.clearTracks();
}
    TrackListControl.prototype = new ListViewControl();
    // clearPlaylist() is like clear(), but also sets the playlist to an empty one
    TrackListControl.prototype.clearTracks = function() {
        this.setTracks([]);
    }
    TrackListControl.prototype.setTracks = function( tracks ) {
        this.tracks = tracks;
        //TODO: Probably better to set up the row information then call parent's _render
        this._render();
    }
    TrackListControl.prototype.appendTrack = function(track) {
        this.tracks.push(track);
        this.appendRow(track.title, track);
    }
    // Returns of list of selected track IDs
    TrackListControl.prototype.getSelectedTracks = function() {
        // First get selected row indexes
        var selected = this.getSelected();
        // Then get track IDs from it
        var tracks = new Array();
        for (i in selected) {
            tracks.push(this.rows[selected[i]].extra);
        }
        return tracks;
    }
    // Extends base class to also remove the item from the track list
    TrackListControl.prototype.deleteItem = function(index) {
        this.tracks.splice(index, 1);
        ListViewControl.prototype.deleteItem.call(this, index);
    }
    // Private methods --------------
    // Recreates every row
    TrackListControl.prototype._render = function() {
        this.clear();
        for (var tracknum in this.tracks) {
            var trackTitle = this.tracks[tracknum].title;
            this.appendRow(trackTitle, this.tracks[tracknum]);
        }
    }

/*************************************
 QueueControl
 ------------
 Definition for the Queue class, which manages the current playlist.
 The queue is basically a specialized subclass of a TrackListControl
 that adds methods for controlling the player and playlist management.
 *************************************/
function QueueControl() {
    TrackListControl.call(this);
    this.currentlyPlaying = null;   // null == nothing playing
    // Events
    page.audio.addEventListener("ended", this.trackFinished, false);
    this.listElement.addEventListener("rowclick", function(e) {
        // Subtract one here to correct for the header row
        e.listControl.playItem(e.row.rowIndex-1);
    }, false);
    this.clearPlaylist();
    // Stick it in the DOM
    document.getElementById("queueContainer").appendChild(this.listElement);
}
    QueueControl.prototype = new TrackListControl();
    QueueControl.prototype.clearPlaylist = function() {
        this.setPlaylist(new Playlist());
    }
    QueueControl.prototype.setPlaylist = function( playlist ) {
        this.playlist = playlist;
        this.setTracks(playlist.items);
    }
    QueueControl.prototype.playItem = function( trackIndex ) {
        var track = this.playlist.items[trackIndex];
        page.audio.src = track.url;
        // TODO: more detailed metadata display
        page.meta.innerHTML = track.title;
        // Start playing
        page.audio.play();
        // Update currently playing highlight
        this.highlightRow(parseInt(trackIndex));
        this.currentlyPlaying = parseInt(trackIndex);
    }
    // Event handlers -----------
    QueueControl.prototype.trackFinished = function(e) {
        if (queue.currentlyPlaying < queue.tracks.length-1) {
            //TODO: vary behavior depending on options (autoplay off, shuffle, etc.)
            queue.playItem(queue.currentlyPlaying + 1);
        }
    }

function Playlist(items, name) {
    if (items == undefined) {
        items = [];
    }
    if (name == undefined) {
        name = "<Unnamed>";
    }
    this.items = items;
    this.name = name;
}

/* Functions
 ************/

// Helper function that gets called at page load and builds a LUT for DOM elements
function bindElementList() {
    list = new Object();

    list.queue =   document.getElementById("queuePane");
    list.sidebar = document.getElementById("sidebarPane");
    list.library = document.getElementById("libraryPane");
    list.audio =   document.getElementById("audioPlayer");
    list.meta =    document.getElementById("metadata");

    // Place it in the global namespace for easy access
    window.page = list;
}
<|endoftext|>


<commit_before>var temp_chart;
var cons_chart;

temp_chart = new Chart(ctx, {
    type: 'line',
    data: {
        datasets: [{
            label: 'Temperature',
            data: [],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
            ],
            borderColor: [
                'rgba(255,99,132,1)',
            ],
            borderWidth: 3
        }]
    },
    options: {
        scales: {
            xAxes: [{
                type: 'time',
                time: {
                    unit: 'second',
                    displayFormats: {
                        second: 'hh:mm:ss'
                    }
                },
                ticks: {
                    autoSkip: true,
                    autoSkipPadding: 20,
                    minRotation: 40
                }
            }],
            yAxes: [{
                ticks: {
                    min: 15,
                    max: 50
                }
            }]
        }
    }
});

function addData(chart, data) {
    chart.data.datasets.forEach((dataset) => {
        dataset.data.push(data);
    });
    chart.update();
}

function removeData(chart) {
    chart.data.datasets.forEach((dataset) => {
        dataset.data.shift();
    });
    chart.update();
}

function add_data_to_temp_chart(temp)
{
    addData(temp_chart, {x: new Date().getTime(), y: temp});
    temp_history.push({x: new Date().getTime(), y: temp});
    counter++;
    if (counter > 20)
    {
        removeData(temp_chart);
        temp_history.shift();
    }
}

function add_data_to_cons_chart(state)
{
    if (state === 'false') state = 0;
    if (state === 'true') state = 1;

    addData(cons_chart, {x: new Date().getTime(), y: state});
    cons_history.push({x: new Date().getTime(), y: state});
    counter++;
    if (counter > 20)
    {
        removeData(cons_chart);
        cons_history.shift();
    }
}

setInterval(function () {
    add_data_to_temp_chart(home_cur_temp);
    add_data_to_cons_chart(home_cur_state);
}, 1000);
<commit_msg>test charts 15<commit_after>var temp_chart;
var cons_chart;

temp_chart = new Chart(ctx, {
    type: 'line',
    data: {
        datasets: [{
            label: 'Temperature',
            data: [],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
            ],
            borderColor: [
                'rgba(255,99,132,1)',
            ],
            borderWidth: 3
        }]
    },
    options: {
        scales: {
            xAxes: [{
                type: 'time',
                time: {
                    unit: 'second',
                    displayFormats: {
                        second: 'hh:mm:ss'
                    }
                },
                ticks: {
                    autoSkip: true,
                    autoSkipPadding: 20,
                    minRotation: 40
                }
            }],
            yAxes: [{
                ticks: {
                    min: 15,
                    max: 50
                }
            }]
        }
    }
});

function addData(chart, data) {
    chart.data.datasets.forEach((dataset) => {
        dataset.data.push(data);
    });
    chart.update();
}

function removeData(chart) {
    chart.data.datasets.forEach((dataset) => {
        dataset.data.shift();
    });
    chart.update();
}

function add_data_to_temp_chart(temp)
{
    if (temp_chart) addData(temp_chart, {x: new Date().getTime(), y: temp});
    temp_history.push({x: new Date().getTime(), y: temp});
    counter++;
    if (counter > 20)
    {
        removeData(temp_chart);
        temp_history.shift();
    }
}

function add_data_to_cons_chart(state)
{
    if (state === 'false') state = 0;
    if (state === 'true') state = 1;

    if (cons_chart) addData(cons_chart, {x: new Date().getTime(), y: state});
    cons_history.push({x: new Date().getTime(), y: state});
    counter++;
    if (counter > 20)
    {
        removeData(cons_chart);
        cons_history.shift();
    }
}

setInterval(function () {
    add_data_to_temp_chart(home_cur_temp);
    add_data_to_cons_chart(home_cur_state);
}, 1000);
<|endoftext|>


<commit_before>  /**
 * The Imazon layer module.
 *
 * @return ImazonLayer class (extends CartoDBLayerClass)
 */
define([
  'moment',
  'uri',
  'abstract/layer/CartoDBLayerClass',
  'text!map/cartocss/forma.cartocss',
  'map/presenters/layers/ImazonLayerPresenter'
], function(moment, UriTemplate, CartoDBLayerClass, FormaCartoCSS, Presenter) {

  'use strict';

  var ImazonLayer = CartoDBLayerClass.extend({
    options: {
      sql: 'SELECT cartodb_id, the_geom_webmercator, to_char(date,\'YYYYMMDD\')::int as date, data_type AS layer, data_type AS name FROM {tableName} ' +
        'WHERE date BETWEEN to_date(\'{startYear}-{startMonth}\',\'YYYY-MM\') AND to_date(\'{endYear}-{endMonth}\',\'YYYY-MM\')',
      cartocss: FormaCartoCSS
    },

    init: function(layer, options, map) {
      this.options.cartocss = FormaCartoCSS.replace(/#date_to_change/g,layer.maxdate.subtract(1, 'months').format('YYYYMMDD'));
      this.presenter = new Presenter(this);
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this._super(layer, options, map);
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    /**
     * Get the CartoDB query.
     *
     * @return {string} CartoDB query
     * @override
     */
    getQuery: function() {
      var query = new UriTemplate(this.options.sql).fillFromObject({
        tableName: this.layer.table_name,
        startMonth: this.currentDate[0].format('MM'),
        startYear: this.currentDate[0].format('YYYY'),
        endMonth: this.currentDate[1].format('MM'),
        endYear: this.currentDate[1].format('YYYY')
      });
      return query;
    }
  });

  return ImazonLayer;

});
<commit_msg>Fix IMAZON SAD date correlation<commit_after>  /**
 * The Imazon layer module.
 *
 * @return ImazonLayer class (extends CartoDBLayerClass)
 */
define([
  'moment',
  'uri',
  'abstract/layer/CartoDBLayerClass',
  'text!map/cartocss/forma.cartocss',
  'map/presenters/layers/ImazonLayerPresenter'
], function(moment, UriTemplate, CartoDBLayerClass, FormaCartoCSS, Presenter) {

  'use strict';

  var ImazonLayer = CartoDBLayerClass.extend({
    options: {
      sql: 'SELECT cartodb_id, the_geom_webmercator, to_char(date,\'YYYYMMDD\')::int as date, data_type AS layer, data_type AS name FROM {tableName} ' +
        'WHERE date BETWEEN to_date(\'{startYear}-{startMonth}\',\'YYYY-MM\') AND to_date(\'{endYear}-{endMonth}\',\'YYYY-MM\')',
      cartocss: FormaCartoCSS
    },

    init: function(layer, options, map) {
      this.options.cartocss = FormaCartoCSS.replace(/#date_to_change/g,layer.maxdate.subtract(1, 'months').utc().format('YYYYMMDD'));
      this.presenter = new Presenter(this);
      this.currentDate = options.currentDate || [moment(layer.mindate), moment(layer.maxdate)];
      this._super(layer, options, map);
    },

    /**
     * Used by UMDLoassLayerPresenter to set the dates for the tile.
     *
     * @param {Array} date 2D array of moment dates [begin, end]
     */
    setCurrentDate: function(date) {
      this.currentDate = date;
      this.updateTiles();
    },

    /**
     * Get the CartoDB query.
     *
     * @return {string} CartoDB query
     * @override
     */
    getQuery: function() {
      var query = new UriTemplate(this.options.sql).fillFromObject({
        tableName: this.layer.table_name,
        startMonth: this.currentDate[0].format('MM'),
        startYear: this.currentDate[0].format('YYYY'),
        endMonth: this.currentDate[1].format('MM'),
        endYear: this.currentDate[1].format('YYYY')
      });
      return query;
    }
  });

  return ImazonLayer;

});
<|endoftext|>


<commit_before>$(function() {

  $('#manual').click(function() {
    $.get('/api/training/alone', function(data) {
      location.href = "/" + data.game.id + '?playUrl=' + encodeURIComponent(data.playUrl);
    });
  });

  function getParameterByName(name) {
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
      results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  var url = getParameterByName('playUrl');
  if (!url) return;

  $(document).on('keypress keydown', function(e) {
    if (e.keyCode == 37) move('west');
    if (e.keyCode == 38) move('north');
    if (e.keyCode == 39) move('east');
    if (e.keyCode == 40) move('south');
    e.preventDefault();
  });

  function move(dir) {
    $.ajax({
      url: url,
      method: 'post',
      data: { dir: dir },
    });
  }

});
<commit_msg>manual.js lock<commit_after>$(function() {

  $('#manual').click(function() {
    $.get('/api/training/alone', function(data) {
      location.href = "/" + data.game.id + '?playUrl=' + encodeURIComponent(data.playUrl);
    });
  });

  function getParameterByName(name) {
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
      results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  }

  var url = getParameterByName('playUrl');
  if (!url) return;

  $(document).on('keypress keydown', function(e) {
    if (e.keyCode == 37) move('west');
    if (e.keyCode == 38) move('north');
    if (e.keyCode == 39) move('east');
    if (e.keyCode == 40) move('south');
    e.preventDefault();
  });

  var lock = false;

  function move(dir) {
    if (!lock) $.ajax({
      url: url,
      method: 'post',
      data: { dir: dir },
      success: function() {
        lock = false;
      }
    });
    lock = true;
  }

});
<|endoftext|>


<commit_before>$(window).on('load', function() {
  // load the data into the dropdown
  var mps = {};

  var data = persons.map(function(p) {
    mps[p.id] = p;

    return {
      id: p.id,
      text: p.name + (p.party ? (' - ' + p.party.abbr) : ''),
    };
  });

  data.sort(function(a, b) {
    return a.text.localeCompare(b.text);
  });

  $(".choose-mp .single-mp").click(function() {
    var selectedId = parseInt($(this).data('id'));
    chooseMP(mps[selectedId]);
  });

  $(".neglected-mps .single-mp").first().click();

  $('#select-dropdown').on("change", function(e) {
    var selectedId = parseInt($(this).val());
    chooseMP(mps[selectedId]);
  });

  $('select.use-select2').select2({
    data: data,
    placeholder: 'Choose an MP',
  });

  $('body').append($(""));
});

/* useful vars */
var selectedMP = null;
var supportsSecret = null;
var emailTxt = ""; // global for preview and then send
// literally whatever data we want to store along with the email
var emailData = {
  allowPublicListing: true // It's an open letter in this campaign
};
var submissionDeferred;

$("#previewEmail").prop("disabled", false);

$(".multiple-choice .option").click(function() {
  var $this = $(this);

  $this.siblings(".multiple-choice .option").removeClass("selected");
  $this.addClass("selected");
  $("#previewEmail").prop("disabled", false);
});

$(".checkbox .option").click(function() {
  var $this = $(this);

  $this.toggleClass("selected");
});

$(".choose-one li").on('click', function(e) {
  var $this = $(this);
  $this.siblings().removeClass('active');
  $this.addClass('active');
});

/* follow-up questions */
var senderSecret = null,
    emailId = null;

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}

function emailSent() {
  ga('send', 'event', 'representation-email', 'sent');

  // prep follow up questions
  var questions = [
    {
      q: "Would you like to get updates about tools such as this?",
      a: ["Yes, please", "No, thanks"],
    },
  ];
  var q = questions[getRandomInt(0, questions.length)];

  ga('send', 'event', 'follow-up', 'asked', q.q);
  $('.follow-up-question p').text(q.q);
  $('#follow-up-answer-1').text(q.a[0]);
  $('#follow-up-answer-2').text(q.a[1]);

  // prep sharing
  $('.twitter-share').data('message', 'I wrote an open letter to ' + selectedMP.name + ' about being heard in Parliament, you should too.');
  $('.fb-share').data('message', 'I wrote an open letter to ' + selectedMP.name + ' about being heard in Parliament, you should too.');

  $("#preview-message").hide();
  $("#message-sent").show();
  pymChild.scrollParentTo('contactmps-embed-parent');
}

$(".follow-up-question-box .toggle-select-follow-up").click(function() {
  var $this = $(this);

  $(".follow-up-question-box .toggle-select-follow-up").removeClass("selected");
  $this.addClass("selected");

  var q = $('.follow-up-question').text().trim();
  var a = $this.text().trim();

  $('.follow-up-question p').text('Thanks!');
  $('.follow-up-answer-box').hide();

  // submit to server
  submissionDeferred.done(function() {
    jQuery.ajax('/api/v1/email/' + emailId + '/qa/', {
      type: 'POST',
      data: {
        question: q,
        answer: a,
        sender_secret: senderSecret,
      },
    });
  });

  ga('send', 'event', 'follow-up', 'answered', q);
});

$("#preview-message").hide();
$("#message-sent").hide();

$("#previewEmail").click(function(e) {
  e.preventDefault();
  var senderName = $(".name-input").val();
  var senderEmail = $(".email-input").val();
  var emailSubject = "Representation of the public in the national assembly";
  var letterContent = $(".letter-content").val();

  if (senderName === '') {
    alert('Please enter your name');
    $('.name-input').focus();
    return;
  }

  if (senderEmail === '') {
    alert('Please enter your email');
    $('.email-input').focus();
    return;
  }

  if (letterContent === '') {
    alert('Please write your letter');
    $('.letter-content').focus();
    return;
  }

  emailTxt = composeMessage();
  emailHtml = emailTxt.replace(/\n/g, '
');

  $("#name").text(senderName);
  $("#email").text(senderEmail);
  $("#email-title").text(emailSubject);
  $("#letter-preview").html(emailHtml);

  $("#build-message").hide();
  $("#preview-message").show();
  location.hash = "#preview-message";

  pymChild.scrollParentTo('contactmps-embed-parent');
});

$("#editMessage").click(function(e) {
  e.preventDefault();
  $("#build-message").show();
  $("#preview-message").hide();
  location.hash = "#email-secret";
  //pymChild.scrollParentTo('contactmps-embed-parent');
});

var reCaptchaValid = false;
var gReCaptchaValidated = function() {
  $("input[type=submit]").removeAttr('disabled');
  reCaptchaValid = true;
};

var gReCaptchaExpired = function() {
  $("input[type=submit]").attr('disabled','disabled');
  reCaptchaValid = false;
};

var recaptchaLoaded = function() {
  grecaptcha.render('recaptcha', {
    'sitekey': recaptchaKey,
    'callback': gReCaptchaValidated,
    'expired-callback': gReCaptchaExpired
  });
  if (typeof pymChild !== undefined) {
    pymChild.sendHeight();
  }
};

var reCaptchaValid = false;
var gReCaptchaValidated = function() {
  $("input[type=submit]").removeAttr('disabled');
  reCaptchaValid = true;
};

var gReCaptchaExpired = function() {
  $("input[type=submit]").attr('disabled','disabled');
  reCaptchaValid = false;
};

var recaptchaLoaded = function() {
  grecaptcha.render('recaptcha', {
    'sitekey': recaptchaKey,
    'callback': gReCaptchaValidated,
    'expired-callback': gReCaptchaExpired
  });
  if (typeof pymChild !== undefined) {
    pymChild.sendHeight();
  }
};

$('#representation').on('submit', submitForm);

function triggerSubmit() {
  $('#representation').submit();
}

function submitForm(e) {
  e.preventDefault();

  var senderName = $(".name-input").val();
  var senderEmail = $(".email-input").val();
  var emailSubject = $("#email-title").text();

  submissionDeferred = jQuery.ajax('/api/v1/email/', {
    type: 'POST',
    data: {
      person: selectedMP.id,
      name: senderName,
      email: senderEmail,
      body: emailTxt,
      subject: emailSubject,
      anyData: JSON.stringify(emailData),
      gRecaptchaResponse: grecaptcha.getResponse(),
      campaign_slug: 'natrepresentation',
    },
    success: function(data) {
      console.info("success", data);

      senderSecret = data.sender_secret;
      emailId = data.secure_id;
    },
    error: function(jqXHR, textStatus, errorThrown) {
      console.error(jqXHR, textStatus, errorThrown, jqXHR.responseText);
    }
  });

  emailSent();
}

// https://stackoverflow.com/a/901144/1305080
function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

function getParentUrl() {
  return getParameterByName('parentUrl');
}

$(function() {
  ga('send', {
    hitType: 'event',
    eventCategory: 'environment',
    eventAction: 'loaded-by-parent-url',
    eventLabel: getParentUrl()
  });
});

var template = "Hon. {{{ recipient_name }}},\n\nAs a democratically elected member of Parliament, you represent me, my concerns and my hopes for the future of South Africa.\n\nI {{{ sufficiently_represented }}}that members of Parliament represent me sufficiently as a citizen, in the National Assembly.\n\n{{{ how_voice_heard }}}.\n\nI would like to be able to raise my concerns about issues of national government with you by {{{ how_should_voice_heard }}}.\n\nMy biggest concerns about South Africa are {{{ concerns }}}.\n\nI believe it is important that I and other South Africans can have our concerns heard by national Government. I hope that we can work together to find effective ways of being heard.\n\nSincerely,\n{{{ sender_name }}}\n{{{ province }}}";

function composeMessage() {
  var sufficientlyRepresentedOption = $('#sufficiently-represented .option.selected').data('value');
  var howVoiceHeardOptions = $('#how-voice-heard .option.selected').map(
    function() { return $(this).data('value'); }).get();
  var howElseVoiceHeard = $('#how-else-voice-heard textarea').val();
  var voiceHeardOutcome = $('#voice-heard-outcome .option.selected').data('value');
  var howShouldVoiceHeard = $('#how-should-voice-heard textarea').val();
  var concerns = $('#concerns textarea').val();
  var senderName = $('input[name=input-name]').val();
  var province = $('input[name=province]').val();
  var sufficientlyRepresented,
      howVoiceHeard;

  if (howElseVoiceHeard !== "")
    howVoiceHeardOptions.push(howElseVoiceHeard);

  if (sufficientlyRepresentedOption === "yes")
    sufficientlyRepresented = "feel ";
  else if (sufficientlyRepresentedOption === "no")
    sufficientlyRepresented = "do not feel ";
  else if (sufficientlyRepresentedOption === "unsure")
    sufficientlyRepresented = "am not sure ";

  var haveTried = "I've sought national representation by ";
  if (howVoiceHeardOptions.length === 0)
    howVoiceHeard = "I have not tried institutional mechanisms for seeking national representation"
  else if (howVoiceHeardOptions.length === 1)
    howVoiceHeard = haveTried + howVoiceHeardOptions[0];
  else if (howVoiceHeardOptions.length === 2)
    howVoiceHeard = haveTried + howVoiceHeardOptions[0] + " and " + howVoiceHeardOptions[1];
  else
    howVoiceHeard = haveTried + howVoiceHeardOptions.slice(0, -1).join(", ") + ", and " + howVoiceHeardOptions.slice(-1)[0];

  var context = {
    'recipient_name': selectedMP.name,
    'sufficiently_represented': sufficientlyRepresented,
    'how_else_voice_heard': howElseVoiceHeard,
    'how_voice_heard': howVoiceHeard,
    'voice_heard_outcome': voiceHeardOutcome,
    'how_should_voice_heard': howShouldVoiceHeard,
    'concerns': concerns,
    'sender_name': senderName,
    'province': province,
  };
  emailData.sufficientlyRepresentedOption = sufficientlyRepresentedOption;
  emailData.sufficientlyRepresented = sufficientlyRepresented;
  emailData.howVoiceHeardOptions = howVoiceHeardOptions;
  emailData.howVoiceHeard = howVoiceHeard;
  emailData.howElseVoiceHEard = howElseVoiceHeard;
  emailData.voiceHeardOutcome = voiceHeardOutcome;
  emailData.howShouldVoiceHeard = howShouldVoiceHeard;
  emailData.concerns = concerns;
  emailData.province = province;

  console.log(emailData);
  return Mustache.render(template, context);
}

function chooseMP(mp) {
  // mark an MP as chosen
  $(".choose-mp .single-mp").removeClass("selected");
  $(".selected-mp-wrap").removeClass("hidden");
  $('.single-mp[data-id=' + mp.id + ']').addClass('selected');
  // we pick up the MP name from here so fix message composition if you change this
  $(".recipient").text(mp.name);
  $(".selected-mp .mp-img-wrapper").css({"background-image": mp.local_portrait_url ? ('url(' + mp.local_portrait_url + ')') : ''});
  $(".selected-mp .mp-img-wrapper .party-logo").attr("src", mp.party ? mp.party.icon_url : '');
  $(".pa-link").attr("href", mp.pa_url);
  $("form input[name=person]").val(mp.id);
  selectedMP = mp;

  composeMessage();
  pymChild.sendHeight();
}
<commit_msg>Document the dog<commit_after>$(window).on('load', function() {
  // load the data into the dropdown
  var mps = {};

  var data = persons.map(function(p) {
    mps[p.id] = p;

    return {
      id: p.id,
      text: p.name + (p.party ? (' - ' + p.party.abbr) : ''),
    };
  });

  data.sort(function(a, b) {
    return a.text.localeCompare(b.text);
  });

  $(".choose-mp .single-mp").click(function() {
    var selectedId = parseInt($(this).data('id'));
    chooseMP(mps[selectedId]);
  });

  $(".neglected-mps .single-mp").first().click();

  $('#select-dropdown').on("change", function(e) {
    var selectedId = parseInt($(this).val());
    chooseMP(mps[selectedId]);
  });

  $('select.use-select2').select2({
    data: data,
    placeholder: 'Choose an MP',
  });

  $('body').append($(""));
});

/* useful vars */
var selectedMP = null;
var supportsSecret = null;
var emailTxt = ""; // global for preview and then send
// literally whatever data we want to store along with the email
var emailData = {
  allowPublicListing: true // It's an open letter in this campaign
};
var submissionDeferred;

$("#previewEmail").prop("disabled", false);

$(".multiple-choice .option").click(function() {
  var $this = $(this);

  $this.siblings(".multiple-choice .option").removeClass("selected");
  $this.addClass("selected");
  $("#previewEmail").prop("disabled", false);
});

$(".checkbox .option").click(function() {
  var $this = $(this);

  $this.toggleClass("selected");
});

$(".choose-one li").on('click', function(e) {
  var $this = $(this);
  $this.siblings().removeClass('active');
  $this.addClass('active');
});

/* follow-up questions */
var senderSecret = null,
    emailId = null;

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}

function emailSent() {
  ga('send', 'event', 'representation-email', 'sent');

  // prep follow up questions
  var questions = [
    {
      q: "Would you like to get updates about tools such as this?",
      a: ["Yes, please", "No, thanks"],
    },
  ];
  var q = questions[getRandomInt(0, questions.length)];

  ga('send', 'event', 'follow-up', 'asked', q.q);
  $('.follow-up-question p').text(q.q);
  $('#follow-up-answer-1').text(q.a[0]);
  $('#follow-up-answer-2').text(q.a[1]);

  // prep sharing
  $('.twitter-share').data('message', 'I wrote an open letter to ' + selectedMP.name + ' about being heard in Parliament, you should too.');
  $('.fb-share').data('message', 'I wrote an open letter to ' + selectedMP.name + ' about being heard in Parliament, you should too.');

  $("#preview-message").hide();
  $("#message-sent").show();
  pymChild.scrollParentTo('contactmps-embed-parent');
}

$(".follow-up-question-box .toggle-select-follow-up").click(function() {
  var $this = $(this);

  $(".follow-up-question-box .toggle-select-follow-up").removeClass("selected");
  $this.addClass("selected");

  var q = $('.follow-up-question').text().trim();
  var a = $this.text().trim();

  $('.follow-up-question p').text('Thanks!');
  $('.follow-up-answer-box').hide();

  // submit to server
  submissionDeferred.done(function() {
    jQuery.ajax('/api/v1/email/' + emailId + '/qa/', {
      type: 'POST',
      data: {
        question: q,
        answer: a,
        sender_secret: senderSecret,
      },
    });
  });

  ga('send', 'event', 'follow-up', 'answered', q);
});

$("#preview-message").hide();
$("#message-sent").hide();

$("#previewEmail").click(function(e) {
  e.preventDefault();
  var senderName = $(".name-input").val();
  var senderEmail = $(".email-input").val();
  var emailSubject = "Representation of the public in the national assembly";
  var letterContent = $(".letter-content").val();

  if (senderName === '') {
    alert('Please enter your name');
    $('.name-input').focus();
    return;
  }

  if (senderEmail === '') {
    alert('Please enter your email');
    $('.email-input').focus();
    return;
  }

  if (letterContent === '') {
    alert('Please write your letter');
    $('.letter-content').focus();
    return;
  }

  emailTxt = composeMessage();
  emailHtml = emailTxt.replace(/\n/g, '
');

  $("#name").text(senderName);
  $("#email").text(senderEmail);
  $("#email-title").text(emailSubject);
  $("#letter-preview").html(emailHtml);

  $("#build-message").hide();
  $("#preview-message").show();
  location.hash = "#preview-message";

  pymChild.scrollParentTo('contactmps-embed-parent');
});

$("#editMessage").click(function(e) {
  e.preventDefault();
  $("#build-message").show();
  $("#preview-message").hide();
  location.hash = "#email-secret";
  //pymChild.scrollParentTo('contactmps-embed-parent');
});

var reCaptchaValid = false;
var gReCaptchaValidated = function() {
  $("input[type=submit]").removeAttr('disabled');
  reCaptchaValid = true;
};

var gReCaptchaExpired = function() {
  $("input[type=submit]").attr('disabled','disabled');
  reCaptchaValid = false;
};

var recaptchaLoaded = function() {
  grecaptcha.render('recaptcha', {
    'sitekey': recaptchaKey,
    'callback': gReCaptchaValidated,
    'expired-callback': gReCaptchaExpired
  });
  if (typeof pymChild !== undefined) {
    pymChild.sendHeight();
  }
};

var reCaptchaValid = false;
var gReCaptchaValidated = function() {
  $("input[type=submit]").removeAttr('disabled');
  reCaptchaValid = true;
};

var gReCaptchaExpired = function() {
  $("input[type=submit]").attr('disabled','disabled');
  reCaptchaValid = false;
};

var recaptchaLoaded = function() {
  grecaptcha.render('recaptcha', {
    'sitekey': recaptchaKey,
    'callback': gReCaptchaValidated,
    'expired-callback': gReCaptchaExpired
  });
  if (typeof pymChild !== undefined) {
    pymChild.sendHeight();
  }
};

$('#representation').on('submit', submitForm);

function triggerSubmit() {
  $('#representation').submit();
}

function submitForm(e) {
  e.preventDefault();

  var senderName = $(".name-input").val();
  var senderEmail = $(".email-input").val();
  var emailSubject = $("#email-title").text();

  submissionDeferred = jQuery.ajax('/api/v1/email/', {
    type: 'POST',
    data: {
      person: selectedMP.id,
      name: senderName,
      email: senderEmail,
      body: emailTxt,
      subject: emailSubject,
      anyData: JSON.stringify(emailData),
      gRecaptchaResponse: grecaptcha.getResponse(),
      campaign_slug: 'natrepresentation',
    },
    success: function(data) {
      console.info("success", data);

      senderSecret = data.sender_secret;
      emailId = data.secure_id;
    },
    error: function(jqXHR, textStatus, errorThrown) {
      console.error(jqXHR, textStatus, errorThrown, jqXHR.responseText);
    }
  });

  emailSent();
}

// https://stackoverflow.com/a/901144/1305080
function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

function getParentUrl() {
  return getParameterByName('parentUrl');
}

$(function() {
  ga('send', {
    hitType: 'event',
    eventCategory: 'environment',
    eventAction: 'loaded-by-parent-url',
    eventLabel: getParentUrl()
  });
});

var template = "Hon. {{{ recipient_name }}},\n\nAs a democratically elected member of Parliament, you represent me, my concerns and my hopes for the future of South Africa.\n\nI {{{ sufficiently_represented }}}that members of Parliament represent me sufficiently as a citizen, in the National Assembly.\n\n{{{ how_voice_heard }}}.\n\nI would like to be able to raise my concerns about issues of national government with you by {{{ how_should_voice_heard }}}.\n\nMy biggest concerns about South Africa are {{{ concerns }}}.\n\nI believe it is important that I and other South Africans can have our concerns heard by national Government. I hope that we can work together to find effective ways of being heard.\n\nSincerely,\n{{{ sender_name }}}\n{{{ province }}}";

function composeMessage() {
  var sufficientlyRepresentedOption = $('#sufficiently-represented .option.selected').data('value');
  var howVoiceHeardOptions = $('#how-voice-heard .option.selected').map(
    function() { return $(this).data('value'); }).get(); // This get() is Reeeeeeally important
  //   ... because without it we have a jQuery collection which doesn't have
  //   ... join and causes cross-site request issues.
  var howElseVoiceHeard = $('#how-else-voice-heard textarea').val();
  var voiceHeardOutcome = $('#voice-heard-outcome .option.selected').data('value');
  var howShouldVoiceHeard = $('#how-should-voice-heard textarea').val();
  var concerns = $('#concerns textarea').val();
  var senderName = $('input[name=input-name]').val();
  var province = $('input[name=province]').val();
  var sufficientlyRepresented,
      howVoiceHeard;

  if (howElseVoiceHeard !== "")
    howVoiceHeardOptions.push(howElseVoiceHeard);

  if (sufficientlyRepresentedOption === "yes")
    sufficientlyRepresented = "feel ";
  else if (sufficientlyRepresentedOption === "no")
    sufficientlyRepresented = "do not feel ";
  else if (sufficientlyRepresentedOption === "unsure")
    sufficientlyRepresented = "am not sure ";

  var haveTried = "I've sought national representation by ";
  if (howVoiceHeardOptions.length === 0)
    howVoiceHeard = "I have not tried institutional mechanisms for seeking national representation"
  else if (howVoiceHeardOptions.length === 1)
    howVoiceHeard = haveTried + howVoiceHeardOptions[0];
  else if (howVoiceHeardOptions.length === 2)
    howVoiceHeard = haveTried + howVoiceHeardOptions[0] + " and " + howVoiceHeardOptions[1];
  else
    howVoiceHeard = haveTried + howVoiceHeardOptions.slice(0, -1).join(", ") + ", and " + howVoiceHeardOptions.slice(-1)[0];

  var context = {
    'recipient_name': selectedMP.name,
    'sufficiently_represented': sufficientlyRepresented,
    'how_else_voice_heard': howElseVoiceHeard,
    'how_voice_heard': howVoiceHeard,
    'voice_heard_outcome': voiceHeardOutcome,
    'how_should_voice_heard': howShouldVoiceHeard,
    'concerns': concerns,
    'sender_name': senderName,
    'province': province,
  };
  emailData.sufficientlyRepresentedOption = sufficientlyRepresentedOption;
  emailData.sufficientlyRepresented = sufficientlyRepresented;
  emailData.howVoiceHeardOptions = howVoiceHeardOptions;
  emailData.howVoiceHeard = howVoiceHeard;
  emailData.howElseVoiceHEard = howElseVoiceHeard;
  emailData.voiceHeardOutcome = voiceHeardOutcome;
  emailData.howShouldVoiceHeard = howShouldVoiceHeard;
  emailData.concerns = concerns;
  emailData.province = province;

  console.log(emailData);
  return Mustache.render(template, context);
}

function chooseMP(mp) {
  // mark an MP as chosen
  $(".choose-mp .single-mp").removeClass("selected");
  $(".selected-mp-wrap").removeClass("hidden");
  $('.single-mp[data-id=' + mp.id + ']').addClass('selected');
  // we pick up the MP name from here so fix message composition if you change this
  $(".recipient").text(mp.name);
  $(".selected-mp .mp-img-wrapper").css({"background-image": mp.local_portrait_url ? ('url(' + mp.local_portrait_url + ')') : ''});
  $(".selected-mp .mp-img-wrapper .party-logo").attr("src", mp.party ? mp.party.icon_url : '');
  $(".pa-link").attr("href", mp.pa_url);
  $("form input[name=person]").val(mp.id);
  selectedMP = mp;

  composeMessage();
  pymChild.sendHeight();
}
<|endoftext|>


<commit_before>// handles search filter toggle functionality
define(
	function() {
  'use strict';

  	// PRIVATE PROPERTIES
  	var _fieldsets = {}; // set of all fieldsets

  	var _searchForm;

  	// main module initialization
  	function init()
  	{
			// capture form submission
			_searchForm = document.getElementById("search-form");
			_searchForm.addEventListener("submit",_formSubmissionHandler,false);

			// Hook all reset buttons on the page and listen for a click event
			var resetBtn = document.querySelectorAll(".reset-btn");
			for (var r = 0;r<resetBtn.length;r++)
				resetBtn[r].addEventListener("click",_resetClicked,false);

			// initialize fieldsets
			var fieldsets = document.querySelectorAll('#search-box fieldset');
			var numFieldsets = fieldsets.length;
			var fs; // individual fieldset

			// instantiate new fieldset objects and place in set of fieldsets
			for (var f = 0; f < numFieldsets; f++)
			{
	      fs = new Fieldset();
	      fs.init(fieldsets[f]);
	      _fieldsets[fs.getId()] = fs;
	    }
  	}

  	function _resetClicked(evt)
  	{
  		for (var f in _fieldsets)
  		{
  			_fieldsets[f].reset()
  		}

  		evt.preventDefault();
  		evt.target.blur();
  	}

  	// Handle form submission
  	function _formSubmissionHandler(evt)
		{
			_triggerFormSubmission(evt.target);
			evt.preventDefault();
		}

		function _triggerFormSubmission(form)
		{
			var input;

			for (var f in _fieldsets)
			{
				input = _fieldsets[f].getSelectedToggle();
				if (input.isAddToggle())
					input = input.getAddInput();
				else
					input = input.getToggle()

				_fieldsets[f].getHidden().value = input.value;
				input.disabled = true;
			}

			var count = 0;
			while(form[count] != undefined)
			{
				input = form[count++];
				if (input.value == "" || (input.type == "radio" || input.type == "checkbox"))
					input.disabled = true;
			}

			form.submit();
		}

		// New ToggleGroup instance constructor
  	var ToggleGroup = function()
  	{
  		var _group; // the group around a toggle
			var _toggle; // the actual toggle input element (radio or checkbox)
			var _label; // the toggle's label element

			var _isCurrentToggle = false;
			var _isAddToggle = false; // the add toggle (if present)
			var _addInput; // the add input text field
			var _addInputLabel; // the add input label
			var _addInputShowing = false; // whether or not the add input field is showing

			function init(tGroup)
			{
				_group = tGroup;
				_toggle = _group.querySelector(".toggle input");
				_label = _group.querySelector("div+label");

				// If input element exists in this toggle it is an add input
				_addInput = _label.querySelector("input");
				_isAddToggle = (_addInput) ? true : false;

				if (_isAddToggle)
				{
					_addInputLabel = _label.querySelector("span");
					if (_addInput.value != "") showAddInput();
				}
				else
				{
					_isCurrentToggle = (_group.parentNode.classList.contains("current-option"));
				}
			}

			// Show the add input text field.
			function showAddInput()
			{
				if (_isAddToggle && !_addInputShowing)
				{
					_addInputLabel.classList.add('hide'); // hide "Add..." text
					_addInput.classList.remove('hide'); // show input field
					_addInputShowing = true;
					setTimeout(function(){ _addInput.focus(); }, 0);
				}
			}

			// Hide the add input text field.
			function hideAddInput()
			{
				if (_isAddToggle && _addInputShowing)
				{
					_addInput.value = ""; // clear input field value
					_addInput.classList.add('hide'); // hide input field
					_addInputLabel.classList.remove('hide'); // show "Add..." text
					_addInputShowing = false;
				}
			}

			// Set the label's text value.
			function setLabel(value)
			{
				if (_isAddToggle)
					_addInputLabel.innerHTML = value;
				else
					_label.innerHTML = value;
			}

			// GETTERS
			function getLabel()
			{
				if (_isAddToggle)
					return _addInputLabel.innerHTML;
				else
					return _label.innerHTML;
			}

			function getToggle()
			{
				return _toggle;
			}

			function getAddInput()
			{
				return _addInput;
			}

			function isAddToggle()
			{
				return _isAddToggle;
			}

			function addInputShowing()
			{
				return _addInputShowing;
			}

			return {
				init:init,
				isAddToggle:isAddToggle,
				showAddInput:showAddInput,
				hideAddInput:hideAddInput,
				setLabel:setLabel,
				getLabel:getLabel,
				getToggle:getToggle,
				getAddInput:getAddInput,
				addInputShowing:addInputShowing
			};
  	}

		// New Fieldset instance constructor
  	var Fieldset = function() {

  		// fieldset components
  		var _fieldset; // the fieldset element
  		var _id; // the fieldset element's id
  		var _legend; // the fieldset's legend
  		var _toggleGroupContainers; // the container for all toggles
  		var _toggleGroups = {}; // array of toggles radio-groups

  		var _highlightToggle; // the currently shown toggle when fieldset is closed
  		var _defaultToggle; // the "All" toggle
  		var _selectedToggle; // the currently selected toggle
  		var _addInputToggle; // add input toggle

  		var _hidden; // the fieldset's hidden input that's used for form submission

  		// if set to true, the form will be submitted the next time the toggle group is closed
  		var _queueUpdate = false;

			function init(fieldset)
			{
				_fieldset = fieldset;
				_id = _fieldset.id;

				_legend = _fieldset.querySelector("legend");

				_toggleGroupContainers 		= _fieldset.querySelectorAll(".options");
				_hidden 									= _fieldset.querySelector("input[type=hidden]");

				var container;
				var groups;
				var group;
				var toggle;

				for (var c = 0; c < _toggleGroupContainers.length; c++)
				{
					groups = _toggleGroupContainers[c].querySelectorAll(".toggle-group");
					for (var g = 0; g < groups.length; g++)
					{
						group = groups[g];
						toggle = new ToggleGroup();
						toggle.init(group);
						_toggleGroups[group.id] = toggle;
						if (toggle.getToggle().checked && c>0)
							_selectedToggle = toggle;

						group.addEventListener("mousedown",_toggleClicked,false);
					}
					_highlightToggle = _highlightToggle || _toggleGroups[groups[0].id];
				}

				_defaultToggle = _toggleGroups[groups[0].id];

				var addInputToggle = _toggleGroups[groups[1].id];
				_addInputToggle = addInputToggle.isAddToggle() ? addInputToggle : null;

				// setup event listeners
				_legend.addEventListener('mousedown',_legendClicked,false);
			}

			// EVENT HANDLERS
			// The legend was clicked.
			function _legendClicked(evt)
			{
				_toggleFilter();
			}

			// Toggle clicked event handler.
			function _toggleClicked(evt)
			{
				var current = evt.target; // the current clicked target
				var toggleGroup = _toggleGroups[evt.currentTarget.id]; // the current toggle group

				var toggle = toggleGroup.getToggle(); // the current toggle input

				// Whether the toggle input or associated label was clicked or not.
				var toggleClicked = (toggle == current || current.getAttribute("for") == toggle.id);

				// If the toggle was not directly clicked, then some other element
				// (such as a div) was clicked in the toggle group, so we need
				// to manually switch the checked state of the toggle.
				// Logic to handle radio buttons and checkboxes differs slightly
				// as clicking a radio button will always set checked to true
				// whereas clicking a check box will toggle its value.
				if (!toggleClicked)
				{
					if (toggle.type == "radio")
						toggle.checked = true;
					else if (toggle.type == "checkbox")
						toggle.checked = !toggle.checked;
				}

				// Toggle filters.
				if (toggleGroup == _highlightToggle)
				{
					_toggleFilter();
				}
				else if (toggleGroup == _addInputToggle)
				{
					_toggleAddInputFilter(current);
				}
				else if (toggleGroup == _selectedToggle)
				{
					_toggleFilter();
				}
				else
				{
					_queueUpdate = true;
					_selectedToggle = toggleGroup;

					// hide add input if selected toggle is not the add input toggle
					if (_addInputToggle && _selectedToggle != _addInputToggle)
						_addInputToggle.hideAddInput();
				}

			}

			// Toggle visible toggle group container. Which means either the
			// currently selected toggle or list of toggles will be visible.
			function _toggleFilter()
			{
				if (_legend.className == 'open')
				{
					if (_queueUpdate)
						_triggerFormSubmission(_searchForm);
					_closeToggle()
				}
				else
				{
					_openToggle();
				}
			}

			// Closes the toggle group
			function _closeToggle()
			{
				// Check if add input value has a value.
				// If it doesn't and the add input toggle is selected
				// uncheck the selected toggle and check the "All"
				// toggle and set the selected toggle to "All".
				var inputVal;
				if (_addInputToggle)
				{
					inputVal = _addInputToggle.getAddInput().value;
					if (_selectedToggle == _addInputToggle && inputVal == "")
					{
						_selectedToggle.getToggle().checked = false;
						_selectedToggle.hideAddInput();
						_selectedToggle = _defaultToggle;
						_defaultToggle.getToggle().checked = true;
					}
				}

				var toggle = _selectedToggle.getToggle();
				_highlightToggle.setLabel(
					inputVal ||
					_selectedToggle.getLabel());

				_toggleGroupContainers[1].classList.add('hide');
				_toggleGroupContainers[0].classList.remove('hide');
				_legend.className = 'closed';
			}

			// Opens the toggle group
			function _openToggle()
			{
				_toggleGroupContainers[1].classList.remove('hide');
				_toggleGroupContainers[0].classList.add('hide');
				_legend.className = 'open';
			}

			function _toggleAddInputFilter(clicked)
			{
				if (_selectedToggle == _addInputToggle)
				{
					// Checking for type text is for IE compatibility
					if (clicked.type != "search" && clicked.type != "text")
						_toggleFilter();
				}
				else
				{
					_selectedToggle = _addInputToggle;
					_selectedToggle.showAddInput();
				}
			}

			function reset()
			{
				if (_legend.className == 'open')
					_closeToggle();

				_selectedToggle.getToggle().checked = false;
				_defaultToggle.getToggle().checked = true;
				if (_addInputToggle) _addInputToggle.hideAddInput();
				_selectedToggle = _defaultToggle;

				_highlightToggle.setLabel(_defaultToggle.getLabel());

				document.getElementById("keyword").value = "";
			}

			// GETTERS
			// Publicly exposed getters for properties
			function getId()
			{
				return _id;
			}

			function getSelectedToggle()
			{
				return _selectedToggle;
			}

			function getHidden()
			{
				return _hidden;
			}

    return {
      init:init,
      getId:getId,
      getSelectedToggle:getSelectedToggle,
      getHidden:getHidden,
      reset:reset
    };

  };

	return {
		init:init
	};
});<commit_msg>Adds update queue to add input toggle<commit_after>// handles search filter toggle functionality
define(
	function() {
  'use strict';

  	// PRIVATE PROPERTIES
  	var _fieldsets = {}; // set of all fieldsets

  	var _searchForm;

  	// main module initialization
  	function init()
  	{
			// capture form submission
			_searchForm = document.getElementById("search-form");
			_searchForm.addEventListener("submit",_formSubmissionHandler,false);

			// Hook all reset buttons on the page and listen for a click event
			var resetBtn = document.querySelectorAll(".reset-btn");
			for (var r = 0;r<resetBtn.length;r++)
				resetBtn[r].addEventListener("click",_resetClicked,false);

			// initialize fieldsets
			var fieldsets = document.querySelectorAll('#search-box fieldset');
			var numFieldsets = fieldsets.length;
			var fs; // individual fieldset

			// instantiate new fieldset objects and place in set of fieldsets
			for (var f = 0; f < numFieldsets; f++)
			{
	      fs = new Fieldset();
	      fs.init(fieldsets[f]);
	      _fieldsets[fs.getId()] = fs;
	    }
  	}

  	function _resetClicked(evt)
  	{
  		for (var f in _fieldsets)
  		{
  			_fieldsets[f].reset()
  		}

  		evt.preventDefault();
  		evt.target.blur();
  	}

  	// Handle form submission
  	function _formSubmissionHandler(evt)
		{
			_triggerFormSubmission(evt.target);
			evt.preventDefault();
		}

		function _triggerFormSubmission(form)
		{
			var input;

			for (var f in _fieldsets)
			{
				input = _fieldsets[f].getSelectedToggle();
				if (input.isAddToggle())
					input = input.getAddInput();
				else
					input = input.getToggle()

				_fieldsets[f].getHidden().value = input.value;
				input.disabled = true;
			}

			var count = 0;
			while(form[count] != undefined)
			{
				input = form[count++];
				if (input.value == "" || (input.type == "radio" || input.type == "checkbox"))
					input.disabled = true;
			}

			form.submit();
		}

		// New ToggleGroup instance constructor
  	var ToggleGroup = function()
  	{
  		var _group; // the group around a toggle
			var _toggle; // the actual toggle input element (radio or checkbox)
			var _label; // the toggle's label element

			var _isCurrentToggle = false;
			var _isAddToggle = false; // the add toggle (if present)
			var _addInput; // the add input text field
			var _addInputLabel; // the add input label
			var _addInputShowing = false; // whether or not the add input field is showing

			function init(tGroup)
			{
				_group = tGroup;
				_toggle = _group.querySelector(".toggle input");
				_label = _group.querySelector("div+label");

				// If input element exists in this toggle it is an add input
				_addInput = _label.querySelector("input");
				_isAddToggle = (_addInput) ? true : false;

				if (_isAddToggle)
				{
					_addInputLabel = _label.querySelector("span");
					if (_addInput.value != "") showAddInput();
				}
				else
				{
					_isCurrentToggle = (_group.parentNode.classList.contains("current-option"));
				}
			}

			// Show the add input text field.
			function showAddInput()
			{
				if (_isAddToggle && !_addInputShowing)
				{
					_addInputLabel.classList.add('hide'); // hide "Add..." text
					_addInput.classList.remove('hide'); // show input field
					_addInputShowing = true;
					setTimeout(function(){ _addInput.focus(); }, 0);
				}
			}

			// Hide the add input text field.
			function hideAddInput()
			{
				if (_isAddToggle && _addInputShowing)
				{
					_addInput.value = ""; // clear input field value
					_addInput.classList.add('hide'); // hide input field
					_addInputLabel.classList.remove('hide'); // show "Add..." text
					_addInputShowing = false;
				}
			}

			// Set the label's text value.
			function setLabel(value)
			{
				if (_isAddToggle)
					_addInputLabel.innerHTML = value;
				else
					_label.innerHTML = value;
			}

			// GETTERS
			function getLabel()
			{
				if (_isAddToggle)
					return _addInputLabel.innerHTML;
				else
					return _label.innerHTML;
			}

			function getToggle()
			{
				return _toggle;
			}

			function getAddInput()
			{
				return _addInput;
			}

			function isAddToggle()
			{
				return _isAddToggle;
			}

			function addInputShowing()
			{
				return _addInputShowing;
			}

			return {
				init:init,
				isAddToggle:isAddToggle,
				showAddInput:showAddInput,
				hideAddInput:hideAddInput,
				setLabel:setLabel,
				getLabel:getLabel,
				getToggle:getToggle,
				getAddInput:getAddInput,
				addInputShowing:addInputShowing
			};
  	}

		// New Fieldset instance constructor
  	var Fieldset = function() {

  		// fieldset components
  		var _fieldset; // the fieldset element
  		var _id; // the fieldset element's id
  		var _legend; // the fieldset's legend
  		var _toggleGroupContainers; // the container for all toggles
  		var _toggleGroups = {}; // array of toggles radio-groups

  		var _highlightToggle; // the currently shown toggle when fieldset is closed
  		var _defaultToggle; // the "All" toggle
  		var _selectedToggle; // the currently selected toggle
  		var _addInputToggle; // add input toggle

  		var _hidden; // the fieldset's hidden input that's used for form submission

  		// if set to true, the form will be submitted the next time the toggle group is closed
  		var _queueUpdate = false;

			function init(fieldset)
			{
				_fieldset = fieldset;
				_id = _fieldset.id;

				_legend = _fieldset.querySelector("legend");

				_toggleGroupContainers 		= _fieldset.querySelectorAll(".options");
				_hidden 									= _fieldset.querySelector("input[type=hidden]");

				var container;
				var groups;
				var group;
				var toggle;

				for (var c = 0; c < _toggleGroupContainers.length; c++)
				{
					groups = _toggleGroupContainers[c].querySelectorAll(".toggle-group");
					for (var g = 0; g < groups.length; g++)
					{
						group = groups[g];
						toggle = new ToggleGroup();
						toggle.init(group);
						_toggleGroups[group.id] = toggle;
						if (toggle.getToggle().checked && c>0)
							_selectedToggle = toggle;

						group.addEventListener("mousedown",_toggleClicked,false);
					}
					_highlightToggle = _highlightToggle || _toggleGroups[groups[0].id];
				}

				_defaultToggle = _toggleGroups[groups[0].id];

				var addInputToggle = _toggleGroups[groups[1].id];
				_addInputToggle = addInputToggle.isAddToggle() ? addInputToggle : null;

				// setup event listeners
				_legend.addEventListener('mousedown',_legendClicked,false);
			}

			// EVENT HANDLERS
			// The legend was clicked.
			function _legendClicked(evt)
			{
				_toggleFilter();
			}

			// Toggle clicked event handler.
			function _toggleClicked(evt)
			{
				var current = evt.target; // the current clicked target
				var toggleGroup = _toggleGroups[evt.currentTarget.id]; // the current toggle group

				var toggle = toggleGroup.getToggle(); // the current toggle input

				// Whether the toggle input or associated label was clicked or not.
				var toggleClicked = (toggle == current || current.getAttribute("for") == toggle.id);

				// If the toggle was not directly clicked, then some other element
				// (such as a div) was clicked in the toggle group, so we need
				// to manually switch the checked state of the toggle.
				// Logic to handle radio buttons and checkboxes differs slightly
				// as clicking a radio button will always set checked to true
				// whereas clicking a check box will toggle its value.
				if (!toggleClicked)
				{
					if (toggle.type == "radio")
						toggle.checked = true;
					else if (toggle.type == "checkbox")
						toggle.checked = !toggle.checked;
				}

				// Toggle filters.
				if (toggleGroup == _highlightToggle)
				{
					_toggleFilter();
				}
				else if (toggleGroup == _addInputToggle)
				{
					_queueUpdate = true;
					_toggleAddInputFilter(current);
				}
				else if (toggleGroup == _selectedToggle)
				{
					_toggleFilter();
				}
				else
				{
					_queueUpdate = true;
					_selectedToggle = toggleGroup;

					// hide add input if selected toggle is not the add input toggle
					if (_addInputToggle && _selectedToggle != _addInputToggle)
						_addInputToggle.hideAddInput();
				}

			}

			// Toggle visible toggle group container. Which means either the
			// currently selected toggle or list of toggles will be visible.
			function _toggleFilter()
			{
				if (_legend.className == 'open')
				{
					if (_queueUpdate)
						_triggerFormSubmission(_searchForm);
					_closeToggle()
				}
				else
				{
					_openToggle();
				}
			}

			// Closes the toggle group
			function _closeToggle()
			{
				// Check if add input value has a value.
				// If it doesn't and the add input toggle is selected
				// uncheck the selected toggle and check the "All"
				// toggle and set the selected toggle to "All".
				var inputVal;
				if (_addInputToggle)
				{
					inputVal = _addInputToggle.getAddInput().value;
					if (_selectedToggle == _addInputToggle && inputVal == "")
					{
						_selectedToggle.getToggle().checked = false;
						_selectedToggle.hideAddInput();
						_selectedToggle = _defaultToggle;
						_defaultToggle.getToggle().checked = true;
					}
				}

				var toggle = _selectedToggle.getToggle();
				_highlightToggle.setLabel(
					inputVal ||
					_selectedToggle.getLabel());

				_toggleGroupContainers[1].classList.add('hide');
				_toggleGroupContainers[0].classList.remove('hide');
				_legend.className = 'closed';
			}

			// Opens the toggle group
			function _openToggle()
			{
				_toggleGroupContainers[1].classList.remove('hide');
				_toggleGroupContainers[0].classList.add('hide');
				_legend.className = 'open';
			}

			function _toggleAddInputFilter(clicked)
			{
				if (_selectedToggle == _addInputToggle)
				{
					// Checking for type text is for IE compatibility
					if (clicked.type != "search" && clicked.type != "text")
						_toggleFilter();
				}
				else
				{
					_selectedToggle = _addInputToggle;
					_selectedToggle.showAddInput();
				}
			}

			function reset()
			{
				if (_legend.className == 'open')
					_closeToggle();

				_selectedToggle.getToggle().checked = false;
				_defaultToggle.getToggle().checked = true;
				if (_addInputToggle) _addInputToggle.hideAddInput();
				_selectedToggle = _defaultToggle;

				_highlightToggle.setLabel(_defaultToggle.getLabel());

				document.getElementById("keyword").value = "";
			}

			// GETTERS
			// Publicly exposed getters for properties
			function getId()
			{
				return _id;
			}

			function getSelectedToggle()
			{
				return _selectedToggle;
			}

			function getHidden()
			{
				return _hidden;
			}

    return {
      init:init,
      getId:getId,
      getSelectedToggle:getSelectedToggle,
      getHidden:getHidden,
      reset:reset
    };

  };

	return {
		init:init
	};
});<|endoftext|>


<commit_before>$(function () {
  $('#search_movie').submit(function(){
    var $form     = $(this);
    var movieName = $form.children('#movie_name_input').val();
    var movieYear = $form.children('#movie_year_input').val();

    var apiUrl    = $form.attr('action') + '/' + movieYear + '/' + movieName;

    $.ajax({
      url: apiUrl,
      beforeSend: function() {
        $('#loading').show();
      },
      success: function(movie){
        var movie_html = '';

        movie_html += '
' + movie.name + ' (' + movie.info.year + ')
';
        movie_html += '';
        movie_html += '
Combined Rating: ' + movie.combined_rating + '
';

        var movie_ratings = '
Ratings:
';

        $.each(movie.ratings, function(rating_site, rating) {
          movie_ratings += '
';
          movie_ratings += rating_site + ':
 ' + rating.score;
        });

        movie_html += movie_ratings;

        $('#loading').hide();
        $('#result').html(movie_html);
      }
    });
    return false;
  });

  $('#movie_name_input').autocomplete({
    source: function(request, response) {
      $.ajax({
        url: '/api/search',
        data: {
          term: request.term
        },
        success: function(data) {
          response($.map(data.movies, function(movie) {
            return {
              label: movie.name + ' (' + movie.year + ')',
              value: movie.name,
              year: movie.year
            }
          }));
        },
      });
    },
    select: function(event,ui) {
      $('#movie_year_input').val(ui.item.year);
      $(this).parents('form').submit();
    },
    minLength: 2
  });
});
<commit_msg>Remove this for now<commit_after>$(function () {
  $('#search_movie').submit(function(){
    var $form     = $(this);
    var movieName = $form.children('#movie_name_input').val();
    var movieYear = $form.children('#movie_year_input').val();

    var apiUrl    = $form.attr('action') + '/' + movieYear + '/' + movieName;

    $.ajax({
      url: apiUrl,
      beforeSend: function() {
        $('#loading').show();
      },
      success: function(movie){
        var movie_html = '';

        movie_html += '
' + movie.name + ' (' + movie.info.year + ')
';
        movie_html += '';
        movie_html += '
Combined Rating: ' + movie.combined_rating + '
';

        var movie_ratings = '
Ratings:
';

        $.each(movie.ratings, function(rating_site, rating) {
          movie_ratings += '
';
          movie_ratings += rating_site + ':
 ' + rating.score;
        });

        movie_html += movie_ratings;

        $('#loading').hide();
        $('#result').html(movie_html);
      }
    });
    return false;
  });

  $('#movie_name_input').autocomplete({
    source: function(request, response) {
      $.ajax({
        url: '/api/search',
        data: {
          term: request.term
        },
        success: function(data) {
          response($.map(data.movies, function(movie) {
            return {
              label: movie.name + ' (' + movie.year + ')',
              value: movie.name,
              year: movie.year
            }
          }));
        },
      });
    },
    select: function(event,ui) {
      $('#movie_year_input').val(ui.item.year);
    },
    minLength: 2
  });
});
<|endoftext|>


<commit_before>/*
 * This is a basic func test for a Serveronly application.
 */
YUI.add('serveronly-headerclient-tests', function (Y) {

    var suite = new Y.Test.Suite("ServerOnly: HeadersClient");

    suite.add(new Y.Test.Case({

	    "test HeadersClient": function() {
	        var that = this,
	            expect = ['keep-alive', 'Keep-Alive'],
	            found = false;
	        Y.one('#p_headers').simulate('click');
            that.wait(function(){
                Y.Assert.areEqual('somevalue', Y.one('#my_header').get('innerHTML'));
                var result = Y.one('#connection').get('innerHTML');
                for(i = 0; i< expect.length; i++){
                    if (result === expect[i]) {
                        found = true;
                    }
                }
                Y.Assert.isTrue(found);
            }, 2000);
        }

    }));

    Y.Test.Runner.add(suite);

}, '0.0.1', {requires: [
    'node', 'node-event-simulate', 'test'
]});
<commit_msg>format change<commit_after>/*
 * This is a basic func test for a Serveronly application.
 */
YUI.add('serveronly-headerclient-tests', function (Y) {

    var suite = new Y.Test.Suite("ServerOnly: HeadersClient");

    suite.add(new Y.Test.Case({

	    "test HeadersClient": function() {
	        var that = this,
	            expect = ['keep-alive', 'Keep-Alive'],
	            found = false;
	        Y.one('#p_headers').simulate('click');
	        that.wait(function(){
                Y.Assert.areEqual('somevalue', Y.one('#my_header').get('innerHTML'));
                var result = Y.one('#connection').get('innerHTML');
                for(i = 0; i< expect.length; i++){
                    if (result === expect[i]) {
                        found = true;
                    }
                }
                Y.Assert.isTrue(found);
            }, 2000);
        }

    }));

    Y.Test.Runner.add(suite);

}, '0.0.1', {requires: [
    'node', 'node-event-simulate', 'test'
]});
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('pilas-blockly', 'Integration | Component | pilas blockly', {
  integration: true
});

test('it renders', function(assert) {
  // Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  this.render(hbs`{{pilas-blockly}}`);
  assert.equal(this.$().text().trim(), 'Ejecutar');
});
<commit_msg>Reparando tests.<commit_after>import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('pilas-blockly', 'Integration | Component | pilas blockly', {
  integration: true
});

test('it renders', function(assert) {
  // Set any properties with this.set('myProperty', 'value');
  // Handle any actions with this.on('myAction', function(val) { ... });

  this.render(hbs`{{pilas-blockly}}`);
  assert.ok(this.$().text().indexOf("Ejecutar") > -1, "Tiene el botón ejecutar visible");
  assert.ok(this.$().text().indexOf("Compartir en twitter") > -1, 'Existe un botón para compartir por twitter');
});
<|endoftext|>


<commit_before>/* global TrelloPowerUp */

var MAPROSOFT_ICON_WITH_TEXT_COLOR = './images/Maprosoft-logo-with-text-color.svg';
var MAPROSOFT_ICON_GRAY = './images/Maprosoft-logo-no-text-gray.svg';
var MAPROSOFT_ICON_COLOR = './images/Maprosoft-logo-no-text-color.svg';
var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';

var CACHED_SHARED_MAP_INFO_KEY = 'cached-shared-map-info';
var TEAM_NAME_KEY = 'maprosoft-team-name';
var TEAM_TOKEN_KEY = 'maprosoft-team-token';

var SETTINGS_SCOPE = 'organization';
var SETTINGS_VISIBILITY = 'shared';

//var Promise = TrelloPowerUp.Promise;
//var t = TrelloPowerUp.iframe();

//var retrieveSharedMapsUrl = 'https://www.maprosoft.com/app/shared?team=demo&getSharedMapNames=yes';
//var cachedMapInfo = {};

var teamNameToKey = function(teamNameOrKey) {
  var key = teamNameOrKey;
  key = key.toLowerCase();
  key = key.replace(' ', '-');
  key = key.replace('\'', '');
  key = key.replace('"', '');
  key = key.replace('~', '');
  key = key.replace('`', '');
  key = key.replace('!', '');
  key = key.replace('@', '');
  key = key.replace('#', '');
  key = key.replace('$', '');
  key = key.replace('%', '');
  key = key.replace('^', '');
  key = key.replace('&', '');
  key = key.replace('*', '');
  key = key.replace('(', '');
  key = key.replace(')', '');
  key = key.replace('{', '');
  key = key.replace('}', '');
  key = key.replace('[', '');
  key = key.replace(']', '');
  key = key.replace(':', '');
  key = key.replace(';', '');
  key = key.replace('.', '');
  key = key.replace('<', '');
  key = key.replace('>', '');
  key = key.replace('?', '');
  key = key.replace('/', '');
  key = key.replace('\\', '');
  key = key.replace('|', '');
  key = key.replace('+', '');
  key = key.replace('=', '');
  key = key.replace('_', '');
  return key;
};

var extractSharedMapNameFromUrl = function(url) {
  var sharedMapName = 'Maprosoft shared map';
  if (url) {
    var decodedUrl = decodeURI(url);
    var urlParts = decodedUrl.split('/');
    if (urlParts && urlParts.length) {
      sharedMapName = urlParts[urlParts.length - 1];
    }
  }
  return sharedMapName;
};

var buildSharedMapUrl = function(teamNameOrKey, sharedMapName) {
  var encodedSharedMapName = encodeURIComponent(sharedMapName);
  var encodedTeamNameOrKey = encodeURIComponent(teamNameOrKey);
  var sharedMapUrl = 'https://www.maprosoft.com/app/shared/' + encodedTeamNameOrKey + '/' + encodedSharedMapName;
  return sharedMapUrl;
};

var buildGeneralMapUrl = function(teamNameOrKey) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/app/map?team=' + teamKey;
};

var buildGeocodeAddressUrl = function(token, address) {
  var encodedAddress = encodeURIComponent(address);
  return 'https://www.maprosoft.com/app/geocode?token=' + token + '&address=' + encodedAddress;
};

var buildTeamSharedMapsUrl = function(teamNameOrKey) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/shared-maps.html?team=' + teamKey;
};

var buildRetrieveSharedMapsUrl = function(teamNameOrKey, token) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/app/shared?team=' + teamKey + '&getSharedMapNames=yes';
};

var buildUrlWithDropPin = function(teamNameOrKey, address, latitude, longitude) {
  var teamKey = teamNameToKey(teamNameOrKey);
  var mapUrl = 'https://www.maprosoft.com/app/map?team=' + teamKey;
  var nextSeparator = '&';
  mapUrl = appendAddressParameters(mapUrl, nextSeparator, address, latitude, longitude);
  return mapUrl;
};

var appendAddressParameters = function(mapUrl, nextSeparator, address, latitude, longitude) {
  var encodedAddress = encodeURIComponent(address);
  return mapUrl + nextSeparator +
      'dropPinTitle=' + encodedAddress +
      '&dropPinLatitude=' + latitude +
      '&dropPinLongitude=' + longitude +
      '&customLatitude=' + latitude +
      '&customLongitude=' + longitude +
      '&customZoom=16';
};

var doGet = function(url) {
  var getPromise = new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = function() {
      try {
        if (request.status === 200) {
          var responseJson = JSON.parse(request.responseText);
          return resolve(responseJson);
        } else if (request.status === 404) {
          return reject(new Error("resource not found."));
        } else {
          return reject(new Error("Unable to load locale, status: " + request.status));
        }
      } catch(ex) {
        return reject(new Error(ex.message));
      }
    };
    request.send();
  });
  return getPromise;
};

var geocodeAddress = function(token, address) {
  var retrieveSharedMapsUrl = buildGeocodeAddressUrl(token, address);
  return doGet(retrieveSharedMapsUrl);
};

var getFreshMapInfo = function(teamName) {
  var token = null;
  var retrieveSharedMapsUrl = buildRetrieveSharedMapsUrl(teamName, token);
  return doGet(retrieveSharedMapsUrl);
};

var formatNPSUrl = function(t, url) {
  if(!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)){
    return null;
  }
  var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
  if (parkShort && parkMap[parkShort]){
    return parkMap[parkShort];
  } else{
    return null;
  }
};

//var getSharedMapInfo = function(t) {
//  return t.get(SETTINGS_SCOPE, SETTINGS_VISIBILITY, CACHED_SHARED_MAP_INFO_KEY, null);
//};

var isMapLinkAttachment = function(attachment) {
  return attachment.url.indexOf('https://www.maprosoft.com/app/map') === 0 || attachment.url.indexOf('https://www.maprosoft.com/app/shared') === 0;
};

var showNoSettingsPopup = function(t) {
  //return t.overlay({
  //  url: './no-settings.html',
  //  args: {}
  //})
  //.then(function () {
  //  return t.closePopup();
  //});

  return t.popup({
    title: 'Settings',
    url: './no-settings.html',
    height: 184
  })
  .then(function () {
    return t.closePopup();
  });
};

// This example is from https://developer.mozilla.org/en-US/docs/Web/Events/resize:
var optimizedResize = (function() {

  var callbacks = [],
      running = false;

  // fired on resize event
  function resize() {

    if (!running) {
      running = true;

      if (window.requestAnimationFrame) {
        window.requestAnimationFrame(runCallbacks);
      } else {
        setTimeout(runCallbacks, 66);
      }
    }

  }

  // run the actual callbacks
  function runCallbacks() {

    callbacks.forEach(function(callback) {
      callback();
    });

    running = false;
  }

  // adds callback to loop
  function addCallback(callback) {

    if (callback) {
      callbacks.push(callback);
    }

  }

  return {
    // public method to add additional callback
    addWindowResizeListener: function(callback) {
      if (!callbacks.length) {
        window.addEventListener('resize', resize);
      }
      addCallback(callback);
    }
  }
}());

<commit_msg>update<commit_after>/* global TrelloPowerUp */

var MAPROSOFT_ICON_WITH_TEXT_COLOR = './images/Maprosoft-logo-with-text-color.svg';
var MAPROSOFT_ICON_GRAY = './images/Maprosoft-logo-no-text-gray.svg';
var MAPROSOFT_ICON_COLOR = './images/Maprosoft-logo-no-text-color.svg';
var WHITE_ICON = './images/icon-white.svg';
var GRAY_ICON = './images/icon-gray.svg';

var CACHED_SHARED_MAP_INFO_KEY = 'cached-shared-map-info';
var TEAM_NAME_KEY = 'maprosoft-team-name';
var TEAM_TOKEN_KEY = 'maprosoft-team-token';

var SETTINGS_SCOPE = 'organization';
var SETTINGS_VISIBILITY = 'shared';

//var Promise = TrelloPowerUp.Promise;
//var t = TrelloPowerUp.iframe();

//var retrieveSharedMapsUrl = 'https://www.maprosoft.com/app/shared?team=demo&getSharedMapNames=yes';
//var cachedMapInfo = {};

var teamNameToKey = function(teamNameOrKey) {
  var key = teamNameOrKey;
  key = key.toLowerCase();
  key = key.replace(' ', '-');
  key = key.replace('\'', '');
  key = key.replace('"', '');
  key = key.replace('~', '');
  key = key.replace('`', '');
  key = key.replace('!', '');
  key = key.replace('@', '');
  key = key.replace('#', '');
  key = key.replace('$', '');
  key = key.replace('%', '');
  key = key.replace('^', '');
  key = key.replace('&', '');
  key = key.replace('*', '');
  key = key.replace('(', '');
  key = key.replace(')', '');
  key = key.replace('{', '');
  key = key.replace('}', '');
  key = key.replace('[', '');
  key = key.replace(']', '');
  key = key.replace(':', '');
  key = key.replace(';', '');
  key = key.replace('.', '');
  key = key.replace('<', '');
  key = key.replace('>', '');
  key = key.replace('?', '');
  key = key.replace('/', '');
  key = key.replace('\\', '');
  key = key.replace('|', '');
  key = key.replace('+', '');
  key = key.replace('=', '');
  key = key.replace('_', '');
  return key;
};

var extractSharedMapNameFromUrl = function(url) {
  var sharedMapName = 'Maprosoft shared map';
  if (url) {
    var decodedUrl = decodeURI(url);
    var urlParts = decodedUrl.split('/');
    if (urlParts && urlParts.length) {
      sharedMapName = urlParts[urlParts.length - 1];
    }
  }
  return sharedMapName;
};

var buildSharedMapUrl = function(teamNameOrKey, sharedMapName) {
  var encodedSharedMapName = encodeURIComponent(sharedMapName);
  var encodedTeamNameOrKey = encodeURIComponent(teamNameOrKey);
  var sharedMapUrl = 'https://www.maprosoft.com/app/shared/' + encodedTeamNameOrKey + '/' + encodedSharedMapName;
  return sharedMapUrl;
};

var buildGeneralMapUrl = function(teamNameOrKey) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/app/map?team=' + teamKey;
};

var buildGeocodeAddressUrl = function(token, address) {
  var encodedAddress = encodeURIComponent(address);
  return 'https://www.maprosoft.com/app/geocode?token=' + token + '&address=' + encodedAddress;
};

var buildTeamSharedMapsUrl = function(teamNameOrKey) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/shared-maps.html?team=' + teamKey;
};

var buildRetrieveSharedMapsUrl = function(teamNameOrKey, token) {
  var teamKey = teamNameToKey(teamNameOrKey);
  return 'https://www.maprosoft.com/app/shared?team=' + teamKey + '&getSharedMapNames=yes';
};

var buildUrlWithDropPin = function(teamNameOrKey, address, latitude, longitude) {
  var teamKey = teamNameToKey(teamNameOrKey);
  var mapUrl = 'https://www.maprosoft.com/app/map?team=' + teamKey;
  var nextSeparator = '&';
  mapUrl = appendAddressParameters(mapUrl, nextSeparator, address, latitude, longitude);
  return mapUrl;
};

var appendAddressParameters = function(mapUrl, nextSeparator, address, latitude, longitude) {
  var encodedAddress = encodeURIComponent(address);
  return mapUrl + nextSeparator +
      'dropPinTitle=' + encodedAddress +
      '&dropPinLatitude=' + latitude +
      '&dropPinLongitude=' + longitude +
      '&customLatitude=' + latitude +
      '&customLongitude=' + longitude +
      '&customZoom=16';
};

var doGet = function(url) {
  var getPromise = new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = function() {
      try {
        if (request.status === 200) {
          var responseJson = JSON.parse(request.responseText);
          return resolve(responseJson);
        } else if (request.status === 404) {
          return reject(new Error("resource not found."));
        } else {
          return reject(new Error("Unable to load locale, status: " + request.status));
        }
      } catch(ex) {
        return reject(new Error(ex.message));
      }
    };
    request.send();
  });
  return getPromise;
};

var geocodeAddress = function(token, address) {
  var retrieveSharedMapsUrl = buildGeocodeAddressUrl(token, address);
  return doGet(retrieveSharedMapsUrl);
};

var getFreshMapInfo = function(teamName) {
  var token = null;
  var retrieveSharedMapsUrl = buildRetrieveSharedMapsUrl(teamName, token);
  return doGet(retrieveSharedMapsUrl);
};

var formatNPSUrl = function(t, url) {
  if(!/^https?:\/\/www\.nps\.gov\/[a-z]{4}\//.test(url)){
    return null;
  }
  var parkShort = /^https?:\/\/www\.nps\.gov\/([a-z]{4})\//.exec(url)[1];
  if (parkShort && parkMap[parkShort]){
    return parkMap[parkShort];
  } else{
    return null;
  }
};

//var getSharedMapInfo = function(t) {
//  return t.get(SETTINGS_SCOPE, SETTINGS_VISIBILITY, CACHED_SHARED_MAP_INFO_KEY, null);
//};

var isMapLinkAttachment = function(attachment) {
  return attachment.url.indexOf('https://www.maprosoft.com/app/map') === 0 || attachment.url.indexOf('https://www.maprosoft.com/app/shared') === 0;
};

var showNoSettingsPopup = function(t) {
  //return t.overlay({
  //  url: './no-settings.html',
  //  args: {}
  //})
  //.then(function () {
  //  return t.closePopup();
  //});

  return t.popup({
    title: 'Settings',
    url: './no-settings.html',
    height: 184
  //})
  //.then(function () {
  //  return t.closePopup();
  });
};

// This example is from https://developer.mozilla.org/en-US/docs/Web/Events/resize:
var optimizedResize = (function() {

  var callbacks = [],
      running = false;

  // fired on resize event
  function resize() {

    if (!running) {
      running = true;

      if (window.requestAnimationFrame) {
        window.requestAnimationFrame(runCallbacks);
      } else {
        setTimeout(runCallbacks, 66);
      }
    }

  }

  // run the actual callbacks
  function runCallbacks() {

    callbacks.forEach(function(callback) {
      callback();
    });

    running = false;
  }

  // adds callback to loop
  function addCallback(callback) {

    if (callback) {
      callbacks.push(callback);
    }

  }

  return {
    // public method to add additional callback
    addWindowResizeListener: function(callback) {
      if (!callbacks.length) {
        window.addEventListener('resize', resize);
      }
      addCallback(callback);
    }
  }
}());

<|endoftext|>


<commit_before>$(function() {
	var requestId = null;
	// create slider with multihanders for year range search.
	var current_year = new Date().getFullYear();
	$('#year-range-slider').slider({
		range: true,
		// gettyimage has image created since 1753, but it makes our slider range too long, we change to later year.
		min: 1900,
		max: current_year,
		values: [ 1970, 2012],
		slide: function(event, ui){
			// showing total year range
			var text = ui.values[0] + ' - ' + ui.values[1];
			$('#startdate').val(ui.values[0]);
			$('#enddate').val(ui.values[1]);
			$('#year-range-text').text(text);
		}
	});
	$('#year-range-text').text( $('#year-range-slider').slider('values', 0 ) + ' - ' + $('#year-range-slider').slider('values', 1 ));

	$('#form-search').on('submit', function(e) {
		e.preventDefault();
		$('.spinner').removeClass('hidden');
		resetTimeline();

		var masterdata = $('#form-search').serializeObject();
		var startdate = masterdata.startdate || $('#year-range-slider').slider('values',0)+'-01-01';
		var enddate = masterdata.enddate || $('#year-range-slider').slider('values',1)+'-01-01';
		startdate = +startdate.split('-')[0];
		enddate = +enddate.split('-')[0];
		var yearlist = [];
		// generate each year
		var range = enddate-startdate;
		var step = parseInt(range/5);
		for (var i=0; i<enddate-startdate; i+=step) {
			yearlist.push(startdate+i);
		}
		//yearlist.push(enddate);
		// itemCount can be only --> 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75
		// limited by gettyimage api
		var itemCount = step*5;
		var limitedCount = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75]
		for( var i =0, limitedLength = limitedCount.length;i<limitedLength;i++){
			if(limitedCount[i]>=itemCount){
				itemCount=limitedCount[i];
				break;
			}
		}
		var reqId = requestId = Math.random();
		var year_mark = null;
		async.mapSeries(yearlist,
			function(year, cb) {
				if (reqId != requestId) {
					// console.log('Cancel expired request')
					return cb();
				}

				var data = clone(masterdata);
				data.startdate = year+'-01-01';
				var nextstep = year+step-1;
				if(nextstep<enddate)
					data.enddate = nextstep+'-12-31';
				else data.enddate = enddate + '-12-31';
				console.log(data.startdate, data.enddate);
				data.itemperpage = itemCount;
				$.ajax({
					url: '/search',
					type: 'GET',
					dataType: 'json',
					data: data,
					resetForm : true
				})
				.done(function(data){
					if (reqId != requestId) return;

						var itemList = [];
						var imageArray = data.SearchForImagesResult&&data.SearchForImagesResult.Images||[];

						$.each(imageArray,function(index, image){
							var date = /\/Date\(([0-9]+).*\)\//g.exec(image.DateCreated);
							if (date && date[1]) image.date = new Date(+date[1]);
							itemList.push(image);
						});

						itemList.sort(function(a, b) {
							return +a.date < +b.date ? -1 : 1;
						});

						// photos
						itemList.forEach(function(image) {
							var year = image.date&&image.date.getFullYear();
							// year mark
							if (typeof year === 'number' && year != year_mark) {
								year_mark = year;
								addOnTimeline(createTextMarker(year), 90, 30);
							}

							var w = +image.MaxImageResolutionWidth || 50;
							var h = +image.MaxImageResolutionHeight || 50;
							var ratio = Math.min(w, h)/Math.max(w, h);
							var size = 60;
							w2 = w > h ? size : size * ratio;
							h2 = w > h ? size * ratio : size;
							addOnTimeline(createSprite(image, {width: w2, height: h2}));
						});

				})
				.fail(function(xhr){
					console.error(xhr);
				})
				.always(function() {
					$('.spinner').addClass('hidden');
					cb();
				});
			},

			function(err, result) {
				// no op
			}
		)
	});

	// submit once on pageload
	$('#form-search').trigger('submit');

	// focus on search box
	$('input[name="query"]').trigger('focus');

	// adding date list staring from 1753
	/*function populateStartDate(){
		var all_selectable_date = '';
		for(var i=1753;i<=current_year;i++){
			if(i===2000) all_selectable_date += '<option value="'+i+'-01-01" selected>'+i+'</option>';
			else all_selectable_date += '<option value="'+i+'-01-01">'+i+'</option>';
		}
		$('#startdate-search').html(all_selectable_date);
	}
	function populateEndDate(selectedVal){
		var selected_startdate = $('#startdate-search option:selected').val();
		var all_selectable_date='';
		for(var i=parseInt(selected_startdate); i<=current_year;i++){
			if(i===parseInt(selectedVal)) all_selectable_date += '<option value="'+i+'-01-01" selected>'+i+'</option>';
			else all_selectable_date += '<option value="'+i+'-01-01">'+i+'</option>';
		}
		$('#enddate-search').html(all_selectable_date);
	}
	populateStartDate();
	populateEndDate(current_year);
	$('#startdate-search').change(function(){
		console.log('startdate change');
		var selected_startdate = $('#startdate-search option:selected').val();
		var selected_enddate = $('#enddate-search option:selected').val();
		if(selected_startdate>selected_enddate){
			$('#enddate-search option[value="'+selected_startdate+'-01-01"]').prop('selected', true);
		}
		populateEndDate(selected_enddate);
	});*/

});

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

function clone(obj) {
  return JSON.parse(JSON.stringify(obj));
};
<commit_msg>Tune again a new initial search value<commit_after>$(function() {
	var requestId = null;
	// create slider with multihanders for year range search.
	var current_year = new Date().getFullYear();
	$('#year-range-slider').slider({
		range: true,
		// gettyimage has image created since 1753, but it makes our slider range too long, we change to later year.
		min: 1900,
		max: current_year,
		values: [ 1972, 2012],
		slide: function(event, ui){
			// showing total year range
			var text = ui.values[0] + ' - ' + ui.values[1];
			$('#startdate').val(ui.values[0]);
			$('#enddate').val(ui.values[1]);
			$('#year-range-text').text(text);
		}
	});
	$('#year-range-text').text( $('#year-range-slider').slider('values', 0 ) + ' - ' + $('#year-range-slider').slider('values', 1 ));

	$('#form-search').on('submit', function(e) {
		e.preventDefault();
		$('.spinner').removeClass('hidden');
		resetTimeline();

		var masterdata = $('#form-search').serializeObject();
		var startdate = masterdata.startdate || $('#year-range-slider').slider('values',0)+'-01-01';
		var enddate = masterdata.enddate || $('#year-range-slider').slider('values',1)+'-01-01';
		startdate = +startdate.split('-')[0];
		enddate = +enddate.split('-')[0];
		var yearlist = [];
		// generate each year
		var range = enddate-startdate;
		var step = parseInt(range/5);
		for (var i=0; i<enddate-startdate; i+=step) {
			yearlist.push(startdate+i);
		}
		//yearlist.push(enddate);
		// itemCount can be only --> 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75
		// limited by gettyimage api
		var itemCount = step*5;
		var limitedCount = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75]
		for( var i =0, limitedLength = limitedCount.length;i<limitedLength;i++){
			if(limitedCount[i]>=itemCount){
				itemCount=limitedCount[i];
				break;
			}
		}
		var reqId = requestId = Math.random();
		var year_mark = null;
		async.mapSeries(yearlist,
			function(year, cb) {
				if (reqId != requestId) {
					// console.log('Cancel expired request')
					return cb();
				}

				var data = clone(masterdata);
				data.startdate = year+'-01-01';
				var nextstep = year+step-1;
				if(nextstep<enddate)
					data.enddate = nextstep+'-12-31';
				else data.enddate = enddate + '-12-31';
				console.log(data.startdate, data.enddate);
				data.itemperpage = itemCount;
				$.ajax({
					url: '/search',
					type: 'GET',
					dataType: 'json',
					data: data,
					resetForm : true
				})
				.done(function(data){
					if (reqId != requestId) return;

						var itemList = [];
						var imageArray = data.SearchForImagesResult&&data.SearchForImagesResult.Images||[];

						$.each(imageArray,function(index, image){
							var date = /\/Date\(([0-9]+).*\)\//g.exec(image.DateCreated);
							if (date && date[1]) image.date = new Date(+date[1]);
							itemList.push(image);
						});

						itemList.sort(function(a, b) {
							return +a.date < +b.date ? -1 : 1;
						});

						// photos
						itemList.forEach(function(image) {
							var year = image.date&&image.date.getFullYear();
							// year mark
							if (typeof year === 'number' && year != year_mark) {
								year_mark = year;
								addOnTimeline(createTextMarker(year), 90, 30);
							}

							var w = +image.MaxImageResolutionWidth || 50;
							var h = +image.MaxImageResolutionHeight || 50;
							var ratio = Math.min(w, h)/Math.max(w, h);
							var size = 60;
							w2 = w > h ? size : size * ratio;
							h2 = w > h ? size * ratio : size;
							addOnTimeline(createSprite(image, {width: w2, height: h2}));
						});

				})
				.fail(function(xhr){
					console.error(xhr);
				})
				.always(function() {
					$('.spinner').addClass('hidden');
					cb();
				});
			},

			function(err, result) {
				// no op
			}
		)
	});

	// submit once on pageload
	$('#form-search').trigger('submit');

	// focus on search box
	$('input[name="query"]').trigger('focus');

	// adding date list staring from 1753
	/*function populateStartDate(){
		var all_selectable_date = '';
		for(var i=1753;i<=current_year;i++){
			if(i===2000) all_selectable_date += '<option value="'+i+'-01-01" selected>'+i+'</option>';
			else all_selectable_date += '<option value="'+i+'-01-01">'+i+'</option>';
		}
		$('#startdate-search').html(all_selectable_date);
	}
	function populateEndDate(selectedVal){
		var selected_startdate = $('#startdate-search option:selected').val();
		var all_selectable_date='';
		for(var i=parseInt(selected_startdate); i<=current_year;i++){
			if(i===parseInt(selectedVal)) all_selectable_date += '<option value="'+i+'-01-01" selected>'+i+'</option>';
			else all_selectable_date += '<option value="'+i+'-01-01">'+i+'</option>';
		}
		$('#enddate-search').html(all_selectable_date);
	}
	populateStartDate();
	populateEndDate(current_year);
	$('#startdate-search').change(function(){
		console.log('startdate change');
		var selected_startdate = $('#startdate-search option:selected').val();
		var selected_enddate = $('#enddate-search option:selected').val();
		if(selected_startdate>selected_enddate){
			$('#enddate-search option[value="'+selected_startdate+'-01-01"]').prop('selected', true);
		}
		populateEndDate(selected_enddate);
	});*/

});

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

function clone(obj) {
  return JSON.parse(JSON.stringify(obj));
};
<|endoftext|>