<commit_before>/* Project specific Javascript goes here. */

function show_plus() {
    // Show/hide verbs that are not interesting
    var showLink = $('<a/>').attr('class', 'plus_link').text('[+]').prop('href', '#');
    $(document).on("click", ".plus_link", toggleHideShow);
    $('.translations a').remove();
    $('.translations').each(function() {
        if ($(this).find('span').size() > 0) {
            $(this).append(showLink);
        }
    });
}

function editable_class_fields() {
    // Edit all editable fields
    $('.vnclass_editable').each(function() {
        $(this).inedit({'onEnd': edited_class_field});
    });

    $('.frame_editable').each(function() {
        $(this).inedit({'onEnd': edited_frame_field});
    });
}

function update_class(here) {
    var vn_class_article = $(here).closest("article")[0];
    var vn_class_id = $(vn_class_article).find("h2").attr("id");

    request = $.ajax({url: '/vn_class/' + vn_class_id + '/'});
    request.done(function(response, textStatus, jqXHR) {
        $(vn_class_article).replaceWith(response);
        show_plus();
        editable_class_fields();
    });

}

/* Validating/refusing translations */
/*
function getColorId(color) {
    if (color == 'both') { return 0; }
    else if (color == 'ladl') { return 1; }
    else if (color == 'lvf') { return 2; }
    else if (color == 'dicovalence') { return 3; }
    else { return 4; }
}

function sortUL(list) {
    list.children(".comma_hack").remove();
    list.children("li").sort(function(a, b) {
        var idA = getColorId($(a).attr('class'));
        var idB = getColorId($(b).attr('class'));

        var upA = $(a).text();
        var upB = $(b).text();
        var cmpText = (upA < upB) ? -1 : (upA > upB) ? 1 : 0;
        return (idA < idB) ? -1 : (idA > idB) ? 1 : cmpText;
    }).appendTo(list);
    span = $('<span />').addClass('comma_hack').text(', ');
    list.find('li').after(span);
}
*/

/* Highlight translations */
function toggleHighlightMembers() {
    var origins = $(this).data('origin').split(',');
    $('.members span').each(function() {
        if (origins.indexOf($(this).text()) != -1) {
            $(this).toggleClass('hover');
        }
    });
}

/* Highlight origins */
function toggleHighlightCandidates() {
    var origin = $(this).text();
    $(this).parent().parent().find('.translations span').each(function() {
        if ($(this).data('origin').split(',').indexOf(origin) != -1) {
            $(this).toggleClass('hover');
        }
    });
}

/* Hide dark/gray translations */
function toggleHideShow(e) {
    e.preventDefault();
    $(this).parent().find('span.unknown').toggle();
    $(this).parent().find('span.dicovalence').toggle();
    $(this).text($(this).text() == '[+]' ? '[-]' : '[+]');
}

// get a cookie using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}

/* Send change to server after edited in place */
function edited_class_field(input_field, span) {
    var new_val = $(input_field).val();
    var vn_class = $(span).parent().attr("id");

    var request = $.ajax({
        url: '/update/',
        type: 'POST',
        data: {vn_class: vn_class, field: $(span).data("field"), label: new_val}
    });

    request.done(function() { update_class(span); });
}

function edited_frame_field(input_field, span) {
    var new_val = $(input_field).val();

    var vn_class_article = $(span).closest("article")[0];
    var vn_class_id = $(vn_class_article).find("h2").attr("id");

    var frame_div = $(span).closest(".frame")[0];
    var frame_id = $(frame_div).data("frameid");

    var request = $.ajax({
        url: '/update/',
        type: 'POST',
        data: {
            field: $(span).data("field"),
            vn_class: vn_class_id,
            frame_id: frame_id,
            label: new_val,
        }
    });

    request.done(function() { update_class(span); });
}

$(document).ready(function() {
    // "Evaluate" a word: set it as valid or not
    /*
    $('.evaluate li').click(function() {
        // Retrieve the word, its status, and the other list
        var word = $(this);
        var wanted = word.parent().hasClass('valid') ? 'invalid': 'valid';
        var other_list = $(this).parent().parent().find('.'+wanted);

        // Move the word to the other list and append a space
        word.hide()
        sortUL(word.parent());

        other_list.append(word);
        span = $('<span />').addClass('comma_hack').text(', ');
        other_list.append(span);
        sortUL(other_list);

        word.fadeIn('slow');
    });
    */

    // Show relation between verbs and origin
    $('.translations span').hover(toggleHighlightMembers, toggleHighlightMembers);
    $('.members span').hover(toggleHighlightCandidates, toggleHighlightCandidates);

    show_plus();

    var csrftoken = getCookie('csrftoken');
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
                // Send the token to same-origin, relative URLs only.
                // Send the token only if the method warrants CSRF protection
                // Using the CSRFToken value acquired earlier
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });

    $(document).ajaxStart(function(e, request, settings) {
        $(".ajax-status").hide();
        $("#ajax-loading").show();
    });
    $(document).ajaxSuccess(function(e, request, settings) {
        if(settings.url.indexOf("vn_class") >= 0) {
            $(".ajax-status").hide();
            $("#ajax-ok").show();
        }
    });
    $(document).ajaxError(function(e, request, settings) {
        alert("Erreur : modification non prise en compte. Je vais regarder ce qui se passe. Merci de rafraichir la page.");
        $(".ajax-status").hide();
        $("#ajax-error").show();
    });

    editable_class_fields();

    // Operations on frames/framesets
    $(document).on('click', '.remove_frame', function() {
        var that = this;
        var vn_class_article = $(this).closest("article")[0];
        var vn_class_id = $(vn_class_article).find("h2").attr("id");

        var frame_div = $(this).closest(".frame")[0];
        var frame_id = $(frame_div).data("frameid");

        var request = $.ajax({
            url: '/remove/',
            type: 'POST',
            data: {
                model: 'VerbNetFrame',
                vn_class: vn_class_id,
                frame_id: frame_id,
                syntax: $(frame_div).find("span[data-field='syntax']").text()
            }
        });

        request.done(function() { update_class(that); });

        return false;
    });

    // new frame
    $(document).on('click', 'button.new_frame', function() {
        $(this).hide();
        var form = $(this).parent().next(".frame");
        form.slideDown();
    });

    $(document).on('submit', 'form.new_frame', function() {
        var that = this;
        var data = $(this).serialize();
        var request = $.post($(this).attr('action'), data);

        request.done(function() { update_class(that); });

        return false;
    });

    // new subclass
    $(document).on('click', 'button.new_subclass', function() {
        var that = this;

        var request = $.ajax({
            url: '/add/',
            type: 'POST',
            data: {
               type: 'subclass',
               frameset_id: $(this).data("frameset_id"),
            }
        });

        request.done(function() { update_class(that); });
        return false;
    });

    // remove subclass
    $(document).on('click', 'button.remove_subclass', function() {
        var that = this;

        var request = $.ajax({
            url: '/remove/',
            type: 'POST',
            data: {
                model: 'VerbNetFrameSet',
                frameset_id: $(this).data("frameset_id"),
            }
        });

        request.done(function() { update_class(that); });
        return false;
    });

});

<commit_msg>Reload the page after any edit<commit_after>/* Project specific Javascript goes here. */

function show_plus() {
    // Show/hide verbs that are not interesting
    var showLink = $('<a/>').attr('class', 'plus_link').text('[+]').prop('href', '#');
    $(document).on("click", ".plus_link", toggleHideShow);
    $('.translations a').remove();
    $('.translations').each(function() {
        if ($(this).find('span').size() > 0) {
            $(this).append(showLink);
        }
    });
}

function editable_class_fields() {
    // Edit all editable fields
    $('.vnclass_editable').each(function() {
        $(this).inedit({'onEnd': edited_class_field});
    });

    $('.frame_editable').each(function() {
        $(this).inedit({'onEnd': edited_frame_field});
    });
}

function update_class(here) {

    location.reload(true);
/*
    var vn_class_article = $(here).closest("article")[0];
    var vn_class_id = $(vn_class_article).find("h2").attr("id");

    request = $.ajax({url: '/vn_class/' + vn_class_id + '/'});
    request.done(function(response, textStatus, jqXHR) {
        $(vn_class_article).replaceWith(response);
        show_plus();
        editable_class_fields();
    });
*/
}

/* Validating/refusing translations */
/*
function getColorId(color) {
    if (color == 'both') { return 0; }
    else if (color == 'ladl') { return 1; }
    else if (color == 'lvf') { return 2; }
    else if (color == 'dicovalence') { return 3; }
    else { return 4; }
}

function sortUL(list) {
    list.children(".comma_hack").remove();
    list.children("li").sort(function(a, b) {
        var idA = getColorId($(a).attr('class'));
        var idB = getColorId($(b).attr('class'));

        var upA = $(a).text();
        var upB = $(b).text();
        var cmpText = (upA < upB) ? -1 : (upA > upB) ? 1 : 0;
        return (idA < idB) ? -1 : (idA > idB) ? 1 : cmpText;
    }).appendTo(list);
    span = $('<span />').addClass('comma_hack').text(', ');
    list.find('li').after(span);
}
*/

/* Highlight translations */
function toggleHighlightMembers() {
    var origins = $(this).data('origin').split(',');
    $('.members span').each(function() {
        if (origins.indexOf($(this).text()) != -1) {
            $(this).toggleClass('hover');
        }
    });
}

/* Highlight origins */
function toggleHighlightCandidates() {
    var origin = $(this).text();
    $(this).parent().parent().find('.translations span').each(function() {
        if ($(this).data('origin').split(',').indexOf(origin) != -1) {
            $(this).toggleClass('hover');
        }
    });
}

/* Hide dark/gray translations */
function toggleHideShow(e) {
    e.preventDefault();
    $(this).parent().find('span.unknown').toggle();
    $(this).parent().find('span.dicovalence').toggle();
    $(this).text($(this).text() == '[+]' ? '[-]' : '[+]');
}

// get a cookie using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}

/* Send change to server after edited in place */
function edited_class_field(input_field, span) {
    var new_val = $(input_field).val();
    var vn_class = $(span).parent().attr("id");

    var request = $.ajax({
        url: '/update/',
        type: 'POST',
        data: {vn_class: vn_class, field: $(span).data("field"), label: new_val}
    });

    request.done(function() { update_class(span); });
}

function edited_frame_field(input_field, span) {
    var new_val = $(input_field).val();

    var vn_class_article = $(span).closest("article")[0];
    var vn_class_id = $(vn_class_article).find("h2").attr("id");

    var frame_div = $(span).closest(".frame")[0];
    var frame_id = $(frame_div).data("frameid");

    var request = $.ajax({
        url: '/update/',
        type: 'POST',
        data: {
            field: $(span).data("field"),
            vn_class: vn_class_id,
            frame_id: frame_id,
            label: new_val,
        }
    });

    request.done(function() { update_class(span); });
}

$(document).ready(function() {
    // "Evaluate" a word: set it as valid or not
    /*
    $('.evaluate li').click(function() {
        // Retrieve the word, its status, and the other list
        var word = $(this);
        var wanted = word.parent().hasClass('valid') ? 'invalid': 'valid';
        var other_list = $(this).parent().parent().find('.'+wanted);

        // Move the word to the other list and append a space
        word.hide()
        sortUL(word.parent());

        other_list.append(word);
        span = $('<span />').addClass('comma_hack').text(', ');
        other_list.append(span);
        sortUL(other_list);

        word.fadeIn('slow');
    });
    */

    // Show relation between verbs and origin
    $('.translations span').hover(toggleHighlightMembers, toggleHighlightMembers);
    $('.members span').hover(toggleHighlightCandidates, toggleHighlightCandidates);

    show_plus();

    var csrftoken = getCookie('csrftoken');
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
                // Send the token to same-origin, relative URLs only.
                // Send the token only if the method warrants CSRF protection
                // Using the CSRFToken value acquired earlier
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });

    $(document).ajaxStart(function(e, request, settings) {
        $(".ajax-status").hide();
        $("#ajax-loading").show();
    });
    $(document).ajaxSuccess(function(e, request, settings) {
        if(settings.url.indexOf("vn_class") >= 0) {
            $(".ajax-status").hide();
            $("#ajax-ok").show();
        }
    });
    $(document).ajaxError(function(e, request, settings) {
        alert("Erreur : modification non prise en compte. Je vais regarder ce qui se passe. Merci de rafraichir la page.");
        $(".ajax-status").hide();
        $("#ajax-error").show();
    });

    editable_class_fields();

    // Operations on frames/framesets
    $(document).on('click', '.remove_frame', function() {
        var that = this;
        var vn_class_article = $(this).closest("article")[0];
        var vn_class_id = $(vn_class_article).find("h2").attr("id");

        var frame_div = $(this).closest(".frame")[0];
        var frame_id = $(frame_div).data("frameid");

        var request = $.ajax({
            url: '/remove/',
            type: 'POST',
            data: {
                model: 'VerbNetFrame',
                vn_class: vn_class_id,
                frame_id: frame_id,
                syntax: $(frame_div).find("span[data-field='syntax']").text()
            }
        });

        request.done(function() { update_class(that); });

        return false;
    });

    // new frame
    $(document).on('click', 'button.new_frame', function() {
        $(this).hide();
        var form = $(this).parent().next(".frame");
        form.slideDown();
    });

    $(document).on('submit', 'form.new_frame', function() {
        var that = this;
        var data = $(this).serialize();
        var request = $.post($(this).attr('action'), data);

        request.done(function() { update_class(that); });

        return false;
    });

    // new subclass
    $(document).on('click', 'button.new_subclass', function() {
        var that = this;

        var request = $.ajax({
            url: '/add/',
            type: 'POST',
            data: {
               type: 'subclass',
               frameset_id: $(this).data("frameset_id"),
            }
        });

        request.done(function() { update_class(that); });
        return false;
    });

    // remove subclass
    $(document).on('click', 'button.remove_subclass', function() {
        var that = this;

        var request = $.ajax({
            url: '/remove/',
            type: 'POST',
            data: {
                model: 'VerbNetFrameSet',
                frameset_id: $(this).data("frameset_id"),
            }
        });

        request.done(function() { update_class(that); });
        return false;
    });

});

<|endoftext|>


<commit_before>function normalizePartyName(name) {
  if (name === undefined) {
    return;
  }
  var slashPos = name.indexOf("/");
  var pos = (slashPos == -1) ? name.length : slashPos;
  return name.toLowerCase().replace("-", "_").substring(0, pos);
}

function normalizeBarWidth(bar_width) {
  var bar_min_size = 7;
  return (bar_width < bar_min_size) ? bar_min_size : bar_width;
}

var parties = ["psoe", "pp", "iu", "ap", "indep", "pa", "bng", "pdp", "erc_am", "esquerra_am", "erc", "hb", "ciu", "cds", "par", "eaj_pnv", "ea", "prc", "pr", "uv"];

var normalization = {
  'paro': 'paro_normalizado',
  'envejecimiento': 'envejecimiento_normalizado'
};

var custom_map_style = [{featureType:"administrative.country",elementType:"all",stylers:[{saturation:-100},{visibility:"off"}]},{featureType:"administrative.province",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"administrative.locality",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"road.arterial",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"all",elementType:"labels",stylers:[{visibility:"off"}]},{featureType:"all",elementType:"all",stylers:[{lightness:7},{saturation:-91}]},{featureType:"all",elementType:"all",stylers:[]}];

var tooltipInfo = {
  "Envejecimiento" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más edad",
    legendBottom:"Menos edad"
  },
  "Edad media" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más edad",
    legendBottom:"Menos edad"
  },
  "PIB per cápita" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más % PIB ",
    legendBottom:"Menos % PIB"
  },
  "Tasa de paro" : {
    content: "Lorem ipsum dolor sit amet de, consectetur adipiscing elit. Donec vel libero ipsum, nec commodo ipsum. Sed elementum, odio et congue.",
    left: "más parados",
    right: "menos parados",
    legendTop: "Más % paro",
    legendBottom:"Menos % paro"
  }
};

var textInfoWindow = {
  "Envejecimiento" : {
    before_positive: "Aquí hay un ",
    after_negative: " menos de personas mayores de 65 años, que en el resto de España",
    before_positive: "Aquí hay un ",
    after_positive: " mas de personas mayores de 65 años, que en el resto de España"
  },
  "Tasa de Paro" : {
    before_positive: "La tasa de paro se encuentra a un ",
    after_negative: " por debajo de la media",
    before_positive: "La tasa de paro se encuentra a un ",
    after_positive: " por encima de la media"
  },
  "PIB per cápita" : {
    before_positive: "El PIB per cápita aquí es un ",
    after_negative: " mas bajo que la media nacional",
    before_positive: "El PIB per cápita aquí es un ",
    after_positive: " mas alto que la media nacional"
  },
  "Edad media" : {
    before_positive: "Su población es ",
    after_negative: " años mas jóven que la media nacional",
    before_positive: "Su población es ",
    after_positive: " años mas mayor que la media nacional"
  },
  "Inmigración" : {
    before_positive: "El porcentaje de inmigración en este municipio está ",
    after_negative: " por debajo de la media",
    before_positive: "El porcentaje de inmigración en este municipio está ",
    after_positive: " por encima de la media"
  },
  "Saldo vegetativo": {
    before_positive: "El crecimiento de la población está un ",
    after_negative: " por debajo de la media",
    before_positive: "El crecimiento de la población está un ",
    after_positive: " por encima de la media"
  },
  "Salario medio": {
    before_positive: "El salario medio aquí está un ",
    after_negative: " por debajo de la media",
    before_positive: "El salario medio aquí está un ",
    after_positive: " por encima de la media"
  },
  "Estudios acabados": {
    before_positive: "Un ",
    after_negative: " menos que la media nacional, tiene los estudios secundarios terminados",
    before_positive: "Un ",
    after_positive: " mas que la media nacional, tiene los estudios secundarios terminados"
  },
  "Penetracion internet": {
    before_positive: "Un ",
    after_negative: " menos que la media, tiene acceso a internet aquí",
    before_positive: "Un ",
    after_positive: " mas que la media, tiene acceso a internet aquí"
  }
};

var table_zoom = {
  12:'gadm4',
  11:'gadm4',
  9:'gadm2',
  8:'gadm2',
  7:'gadm2',
  6:'gadm1'
};

var procesos_electorales = {
  "1987":"68","1988":"68","1989":"68","1990":"68",
  "1991":"69","1992":"69","1993":"69","1994":"69",
  "1995":"70","1996":"70","1997":"70","1998":"70",
  "1999":"71","2000":"71","2001":"71","2002":"71",
  "2003":"72","2004":"72","2005":"72","2006":"72",
  "2007":"73","2008":"73","2009":"73","2010":"73",
  "2011":"74"
};

var paro = [1999, 2003, 2007];

//var graph_hack_year = {
// "1987":"1987","1988":"1987","1989":"1987","1990":"1987",
//  "1991":"1991","1992":"1991","1993":"1991","1994":"1991",
//  "1995":"1995","1996":"1995","1997":"1995","1998":"1995",
//  "1999":"1999","2000":"1999","2001":"1999","2002":"1999",
//  "2003":"2003","2004":"2003","2005":"2003","2006":"2003",
//  "2007":"2007","2008":"2007","2009":"2007","2010":"2007",
//  "2011":"74"
//};
<commit_msg>We don't use graph_hack_year anymore.<commit_after>function normalizePartyName(name) {
  if (name === undefined) {
    return;
  }
  var slashPos = name.indexOf("/");
  var pos = (slashPos == -1) ? name.length : slashPos;
  return name.toLowerCase().replace("-", "_").substring(0, pos);
}

function normalizeBarWidth(bar_width) {
  var bar_min_size = 7;
  return (bar_width < bar_min_size) ? bar_min_size : bar_width;
}

var parties = ["psoe", "pp", "iu", "ap", "indep", "pa", "bng", "pdp", "erc_am", "esquerra_am", "erc", "hb", "ciu", "cds", "par", "eaj_pnv", "ea", "prc", "pr", "uv"];

var normalization = {
  'paro': 'paro_normalizado',
  'envejecimiento': 'envejecimiento_normalizado'
};

var custom_map_style = [{featureType:"administrative.country",elementType:"all",stylers:[{saturation:-100},{visibility:"off"}]},{featureType:"administrative.province",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"administrative.locality",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"road.arterial",elementType:"all",stylers:[{visibility:"off"}]},{featureType:"all",elementType:"labels",stylers:[{visibility:"off"}]},{featureType:"all",elementType:"all",stylers:[{lightness:7},{saturation:-91}]},{featureType:"all",elementType:"all",stylers:[]}];

var tooltipInfo = {
  "Envejecimiento" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más edad",
    legendBottom:"Menos edad"
  },
  "Edad media" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más edad",
    legendBottom:"Menos edad"
  },
  "PIB per cápita" : {
    content: "Desviación respecto a la media de edad de cada municipio.",
    left: "más mayores",
    right: "más jóvenes",
    legendTop: "Más % PIB ",
    legendBottom:"Menos % PIB"
  },
  "Tasa de paro" : {
    content: "Lorem ipsum dolor sit amet de, consectetur adipiscing elit. Donec vel libero ipsum, nec commodo ipsum. Sed elementum, odio et congue.",
    left: "más parados",
    right: "menos parados",
    legendTop: "Más % paro",
    legendBottom:"Menos % paro"
  }
};

var textInfoWindow = {
  "Envejecimiento" : {
    before_positive: "Aquí hay un ",
    after_negative: " menos de personas mayores de 65 años, que en el resto de España",
    before_positive: "Aquí hay un ",
    after_positive: " mas de personas mayores de 65 años, que en el resto de España"
  },
  "Tasa de Paro" : {
    before_positive: "La tasa de paro se encuentra a un ",
    after_negative: " por debajo de la media",
    before_positive: "La tasa de paro se encuentra a un ",
    after_positive: " por encima de la media"
  },
  "PIB per cápita" : {
    before_positive: "El PIB per cápita aquí es un ",
    after_negative: " mas bajo que la media nacional",
    before_positive: "El PIB per cápita aquí es un ",
    after_positive: " mas alto que la media nacional"
  },
  "Edad media" : {
    before_positive: "Su población es ",
    after_negative: " años mas jóven que la media nacional",
    before_positive: "Su población es ",
    after_positive: " años mas mayor que la media nacional"
  },
  "Inmigración" : {
    before_positive: "El porcentaje de inmigración en este municipio está ",
    after_negative: " por debajo de la media",
    before_positive: "El porcentaje de inmigración en este municipio está ",
    after_positive: " por encima de la media"
  },
  "Saldo vegetativo": {
    before_positive: "El crecimiento de la población está un ",
    after_negative: " por debajo de la media",
    before_positive: "El crecimiento de la población está un ",
    after_positive: " por encima de la media"
  },
  "Salario medio": {
    before_positive: "El salario medio aquí está un ",
    after_negative: " por debajo de la media",
    before_positive: "El salario medio aquí está un ",
    after_positive: " por encima de la media"
  },
  "Estudios acabados": {
    before_positive: "Un ",
    after_negative: " menos que la media nacional, tiene los estudios secundarios terminados",
    before_positive: "Un ",
    after_positive: " mas que la media nacional, tiene los estudios secundarios terminados"
  },
  "Penetracion internet": {
    before_positive: "Un ",
    after_negative: " menos que la media, tiene acceso a internet aquí",
    before_positive: "Un ",
    after_positive: " mas que la media, tiene acceso a internet aquí"
  }
};

var table_zoom = {
  12:'gadm4',
  11:'gadm4',
  9:'gadm2',
  8:'gadm2',
  7:'gadm2',
  6:'gadm1'
};

var procesos_electorales = {
  "1987":"68","1988":"68","1989":"68","1990":"68",
  "1991":"69","1992":"69","1993":"69","1994":"69",
  "1995":"70","1996":"70","1997":"70","1998":"70",
  "1999":"71","2000":"71","2001":"71","2002":"71",
  "2003":"72","2004":"72","2005":"72","2006":"72",
  "2007":"73","2008":"73","2009":"73","2010":"73",
  "2011":"74"
};

//var graph_hack_year = {
// "1987":"1987","1988":"1987","1989":"1987","1990":"1987",
//  "1991":"1991","1992":"1991","1993":"1991","1994":"1991",
//  "1995":"1995","1996":"1995","1997":"1995","1998":"1995",
//  "1999":"1999","2000":"1999","2001":"1999","2002":"1999",
//  "2003":"2003","2004":"2003","2005":"2003","2006":"2003",
//  "2007":"2007","2008":"2007","2009":"2007","2010":"2007",
//  "2011":"74"
//};
<|endoftext|>


<commit_before>"use strict";

var webcomponentsUtils = {
    importScope: function(callback) {
        callback(document._currentScript.ownerDocument);
    },
    registerElement: function(tagName, registerCallbacks) {
        var proto = Object.create(HTMLElement.prototype);
        registerCallbacks.call(proto);
        document.registerElement(tagName, {prototype: proto});
    },
    addTemplate: function(element, template) {
        element.appendChild(webcomponentsUtils.cloneTemplate(template));
        return element.lastElementChild;
    },
    cloneTemplate: function(template) {
        return document.importNode(template.content, true);
    },
    appendChildren: function(children, newParent) {
        for (var i = 0; i < children.length; i++) {
            newParent.appendChild(children[i]);
        }
    },
    prependChildren: function(children, newParent) {
        for (var i = children.length - 1; i >= 0; i--) {
            newParent.insertBefore(children[i], newParent.firstElementChild);
        }
    },
    /**
     *
     * @param from, either HTMLElement or an Array of Attributes
     * @param to, either HTMLElement or an Array of HTMLElement
     */
    passAllAttributes: function(from, to) {
        if (to.constructor === HTMLCollection) {
            for (var i = 0; i < to.length; i++) {
                webcomponentsUtils.passAllAttributes(from, to[i]);
            }
        } else {
            for (var i = 0; i < from.attributes.length; i++) {
                var attribute = from.attributes[i];
                to.setAttribute(attribute.name, attribute.value);
            }
        }
    }
};

var htmlUtils = {
    escapeHtml: function(htmlString) {
        return htmlString
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
    },
    getAttributeValue: function(e, attribute) {
        var attr = e.attributes.getNamedItem(attribute);
        if (attr) {
            return attr.value;
        }
        return undefined;
    },
    scrollTo: function(id) {
        if (!arguments.length) {
            id = location.hash.substring(location.hash.indexOf('#') + 1);
        }
        if (typeof id === 'string') {
            id = document.getElementById(id);
        }

        if (id) {
            id.scrollIntoView(true);
        }
    },
    toElement: function(htmlString) {
        var template = document.createElement('template');
        template.innerHTML = htmlString;
        return template.content.firstChild;
    },
    clear: function(e) {
        while (e.firstChild) {
            e.removeChild(e.firstChild);
        }
    },
    removeClassFromElements: function(clazz) {
        var elements = document.getElementsByClassName(clazz);
        while (elements.length) {
            elements[0].classList.remove(clazz);
        }
    },
    getParameterByName: function(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, " "));
    }
};

var mathUtils = {
    trimToRange: function(value, from, to) {
        if (value < from) {
            return from;
        } else if (value > to) {
            return to;
        } else {
            return value;
        }
    },
    toRadians: function(degree) {
        return degree * (Math.PI / 180);
    },
    toDegrees: function(radians) {
        return radians * (180 / Math.PI);
    },
    distance: function(x1, y1, x2, y2) {
        x2 = x2 || 0;
        y2 = y2 || 0;
        return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
    }
};

var colorUtils = {
    hexToRGB: function(hex) {
        if (typeof hex === 'string') {
            hex = hex.replace('#', '');
        }
        hex = parseInt(hex, 16);
        var r = hex >> 16;
        var g = hex >> 8 & 0xFF;
        var b = hex & 0xFF;
        return {r: r, g: g, b: b};
    },
    hexToRGBA: function(hex, a) {
        var rgb = hexToRGB(hex);
        rgb.a = a;
        return rgb;
    },
    rgbToHex: function(rgb, addLeadingHash) {
        var r = 0;
        var g = 0;
        var b = 0;
        if (arguments.length < 3) {
            r = rgb.r;
            g = rgb.g;
            b = rgb.b;
        } else {
            r = arguments[0];
            g = arguments[1];
            b = arguments[2];
        }

        r = numberUtils.pad(mathUtils.trimToRange(r, 0, 255).toString(16), 2);
        g = numberUtils.pad(mathUtils.trimToRange(g, 0, 255).toString(16), 2);
        b = numberUtils.pad(mathUtils.trimToRange(b, 0, 255).toString(16), 2);

        return ((addLeadingHash) ? '#' : '') + r + g + b;
    },
    rgba: function(rgba) {
        var r = 0;
        var g = 0;
        var b = 0;
        var a = 0;
        if (arguments.length === 1) {
            r = rgba.r;
            g = rgba.g;
            b = rgba.b;
            a = rgba.a;
        } else {
            r = arguments[0];
            g = arguments[1];
            b = arguments[2];
            a = arguments[3];
        }
        return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')';
    },
    increaseBrightnessColor: function(hex, by) {
        var c = colorUtils.hexToRGB(hex);
        c.r += by;
        c.g += by;
        c.b += by;
        return colorUtils.rgbToHex(c, true);
    }
};

var numberUtils = {
    pad: function(num, size) {
        var s = num + "";
        while (s.length < size) s = "0" + s;
        return s;
    }
};
<commit_msg>Fix undefined function reference hexToRGB<commit_after>"use strict";

var webcomponentsUtils = {
    importScope: function(callback) {
        callback(document._currentScript.ownerDocument);
    },
    registerElement: function(tagName, registerCallbacks) {
        var proto = Object.create(HTMLElement.prototype);
        registerCallbacks.call(proto);
        document.registerElement(tagName, {prototype: proto});
    },
    addTemplate: function(element, template) {
        element.appendChild(webcomponentsUtils.cloneTemplate(template));
        return element.lastElementChild;
    },
    cloneTemplate: function(template) {
        return document.importNode(template.content, true);
    },
    appendChildren: function(children, newParent) {
        for (var i = 0; i < children.length; i++) {
            newParent.appendChild(children[i]);
        }
    },
    prependChildren: function(children, newParent) {
        for (var i = children.length - 1; i >= 0; i--) {
            newParent.insertBefore(children[i], newParent.firstElementChild);
        }
    },
    /**
     *
     * @param from, either HTMLElement or an Array of Attributes
     * @param to, either HTMLElement or an Array of HTMLElement
     */
    passAllAttributes: function(from, to) {
        if (to.constructor === HTMLCollection) {
            for (var i = 0; i < to.length; i++) {
                webcomponentsUtils.passAllAttributes(from, to[i]);
            }
        } else {
            for (var i = 0; i < from.attributes.length; i++) {
                var attribute = from.attributes[i];
                to.setAttribute(attribute.name, attribute.value);
            }
        }
    }
};

var htmlUtils = {
    escapeHtml: function(htmlString) {
        return htmlString
            .replace(/&/g, "&")
            .replace(/</g, "<")
            .replace(/>/g, ">")
            .replace(/"/g, """)
            .replace(/'/g, "'");
    },
    getAttributeValue: function(e, attribute) {
        var attr = e.attributes.getNamedItem(attribute);
        if (attr) {
            return attr.value;
        }
        return undefined;
    },
    scrollTo: function(id) {
        if (!arguments.length) {
            id = location.hash.substring(location.hash.indexOf('#') + 1);
        }
        if (typeof id === 'string') {
            id = document.getElementById(id);
        }

        if (id) {
            id.scrollIntoView(true);
        }
    },
    toElement: function(htmlString) {
        var template = document.createElement('template');
        template.innerHTML = htmlString;
        return template.content.firstChild;
    },
    clear: function(e) {
        while (e.firstChild) {
            e.removeChild(e.firstChild);
        }
    },
    removeClassFromElements: function(clazz) {
        var elements = document.getElementsByClassName(clazz);
        while (elements.length) {
            elements[0].classList.remove(clazz);
        }
    },
    getParameterByName: function(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, " "));
    }
};

var mathUtils = {
    trimToRange: function(value, from, to) {
        if (value < from) {
            return from;
        } else if (value > to) {
            return to;
        } else {
            return value;
        }
    },
    toRadians: function(degree) {
        return degree * (Math.PI / 180);
    },
    toDegrees: function(radians) {
        return radians * (180 / Math.PI);
    },
    distance: function(x1, y1, x2, y2) {
        x2 = x2 || 0;
        y2 = y2 || 0;
        return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
    }
};

var colorUtils = {
    hexToRGB: function(hex) {
        if (typeof hex === 'string') {
            hex = hex.replace('#', '');
        }
        hex = parseInt(hex, 16);
        var r = hex >> 16;
        var g = hex >> 8 & 0xFF;
        var b = hex & 0xFF;
        return {r: r, g: g, b: b};
    },
    hexToRGBA: function(hex, a) {
        var rgb = colorUtils.hexToRGB(hex);
        rgb.a = a;
        return rgb;
    },
    rgbToHex: function(rgb, addLeadingHash) {
        var r = 0;
        var g = 0;
        var b = 0;
        if (arguments.length < 3) {
            r = rgb.r;
            g = rgb.g;
            b = rgb.b;
        } else {
            r = arguments[0];
            g = arguments[1];
            b = arguments[2];
        }

        r = numberUtils.pad(mathUtils.trimToRange(r, 0, 255).toString(16), 2);
        g = numberUtils.pad(mathUtils.trimToRange(g, 0, 255).toString(16), 2);
        b = numberUtils.pad(mathUtils.trimToRange(b, 0, 255).toString(16), 2);

        return ((addLeadingHash) ? '#' : '') + r + g + b;
    },
    rgba: function(rgba) {
        var r = 0;
        var g = 0;
        var b = 0;
        var a = 0;
        if (arguments.length === 1) {
            r = rgba.r;
            g = rgba.g;
            b = rgba.b;
            a = rgba.a;
        } else {
            r = arguments[0];
            g = arguments[1];
            b = arguments[2];
            a = arguments[3];
        }
        return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')';
    },
    increaseBrightnessColor: function(hex, by) {
        var c = colorUtils.hexToRGB(hex);
        c.r += by;
        c.g += by;
        c.b += by;
        return colorUtils.rgbToHex(c, true);
    }
};

var numberUtils = {
    pad: function(num, size) {
        var s = num + "";
        while (s.length < size) s = "0" + s;
        return s;
    }
};
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

/* eslint-env node */

'use strict';

const {transformSync: babelTransformSync} = require('@babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
 * found when Flow v0.54 was deployed. To see the error delete this comment and
 * run Flow. */
const babelRegisterOnly = require('metro-babel-register');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
 * found when Flow v0.54 was deployed. To see the error delete this comment and
 * run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('@babel/generator').default;

const nodeFiles = new RegExp(
  [
    '/local-cli/',
    '/metro(?:-[^/]*)?/', // metro, metro-core, metro-source-map, metro-etc
  ].join('|'),
);
const nodeOptions = babelRegisterOnly.config([nodeFiles]);

babelRegisterOnly([]);

/* $FlowFixMe(site=react_native_oss) */
const transformer = require('metro/src/reactNativeTransformer');
module.exports = {
  process(src /*: string */, file /*: string */) {
    if (nodeFiles.test(file)) {
      // node specific transforms only
      return babelTransformSync(src, {
        filename: file,
        sourceType: 'script',
        ...nodeOptions,
        ast: false,
      }).code;
    }

    const {ast} = transformer.transform({
      filename: file,
      localPath: file,
      options: {
        ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044
        dev: true,
        inlineRequires: true,
        minify: false,
        platform: '',
        projectRoot: '',
        retainLines: true,
        sourceType: 'unambiguous', // b7 required. detects module vs script mode
      },
      src,
      plugins: [
        [require('@babel/plugin-transform-block-scoping')],
        // the flow strip types plugin must go BEFORE class properties!
        // there'll be a test case that fails if you don't.
        [require('@babel/plugin-transform-flow-strip-types')],
        [
          require('@babel/plugin-proposal-class-properties'),
          // use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
          {loose: true},
        ],
        [require('@babel/plugin-transform-computed-properties')],
        [require('@babel/plugin-transform-destructuring')],
        [require('@babel/plugin-transform-function-name')],
        [require('@babel/plugin-transform-literals')],
        [require('@babel/plugin-transform-parameters')],
        [require('@babel/plugin-transform-shorthand-properties')],
        [require('@babel/plugin-transform-react-jsx')],
        [require('@babel/plugin-transform-regenerator')],
        [require('@babel/plugin-transform-sticky-regex')],
        [require('@babel/plugin-transform-unicode-regex')],
        [
          require('@babel/plugin-transform-modules-commonjs'),
          {strict: false, allowTopLevelThis: true},
        ],
        [require('@babel/plugin-transform-classes')],
        [require('@babel/plugin-transform-arrow-functions')],
        [require('@babel/plugin-transform-spread')],
        [require('@babel/plugin-proposal-object-rest-spread')],
        [
          require('@babel/plugin-transform-template-literals'),
          {loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
        ],
        [require('@babel/plugin-transform-exponentiation-operator')],
        [require('@babel/plugin-transform-object-assign')],
        [require('@babel/plugin-transform-for-of'), {loose: true}],
        [require('@babel/plugin-transform-react-display-name')],
        [require('@babel/plugin-transform-react-jsx-source')],
      ],
    });

    return generate(
      ast,
      {
        code: true,
        comments: false,
        compact: false,
        filename: file,
        retainLines: true,
        sourceFileName: file,
        sourceMaps: true,
      },
      src,
    ).code;
  },

  getCacheKey: createCacheKeyFunction([
    __filename,
    require.resolve('metro/src/reactNativeTransformer'),
    require.resolve('@babel/core/package.json'),
  ]),
};
<commit_msg>Use babel runtime instead of relying on global babelHelpers and regenerator (#198)<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

/* eslint-env node */

'use strict';

const {transformSync: babelTransformSync} = require('@babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
 * found when Flow v0.54 was deployed. To see the error delete this comment and
 * run Flow. */
const babelRegisterOnly = require('metro-babel-register');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
 * found when Flow v0.54 was deployed. To see the error delete this comment and
 * run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('@babel/generator').default;

const nodeFiles = new RegExp(
  [
    '/local-cli/',
    '/metro(?:-[^/]*)?/', // metro, metro-core, metro-source-map, metro-etc
  ].join('|'),
);
const nodeOptions = babelRegisterOnly.config([nodeFiles]);

babelRegisterOnly([]);

/* $FlowFixMe(site=react_native_oss) */
const transformer = require('metro/src/reactNativeTransformer');
module.exports = {
  process(src /*: string */, file /*: string */) {
    if (nodeFiles.test(file)) {
      // node specific transforms only
      return babelTransformSync(src, {
        filename: file,
        sourceType: 'script',
        ...nodeOptions,
        ast: false,
      }).code;
    }

    const {ast} = transformer.transform({
      filename: file,
      localPath: file,
      options: {
        ast: true, // needed for open source (?) https://github.com/facebook/react-native/commit/f8d6b97140cffe8d18b2558f94570c8d1b410d5c#r28647044
        dev: true,
        disableBabelRuntime: true,
        inlineRequires: true,
        minify: false,
        platform: '',
        projectRoot: '',
        retainLines: true,
        sourceType: 'unambiguous', // b7 required. detects module vs script mode
      },
      src,
      plugins: [
        [require('@babel/plugin-transform-block-scoping')],
        // the flow strip types plugin must go BEFORE class properties!
        // there'll be a test case that fails if you don't.
        [require('@babel/plugin-transform-flow-strip-types')],
        [
          require('@babel/plugin-proposal-class-properties'),
          // use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
          {loose: true},
        ],
        [require('@babel/plugin-transform-computed-properties')],
        [require('@babel/plugin-transform-destructuring')],
        [require('@babel/plugin-transform-function-name')],
        [require('@babel/plugin-transform-literals')],
        [require('@babel/plugin-transform-parameters')],
        [require('@babel/plugin-transform-shorthand-properties')],
        [require('@babel/plugin-transform-react-jsx')],
        [require('@babel/plugin-transform-regenerator')],
        [require('@babel/plugin-transform-sticky-regex')],
        [require('@babel/plugin-transform-unicode-regex')],
        [
          require('@babel/plugin-transform-modules-commonjs'),
          {strict: false, allowTopLevelThis: true},
        ],
        [require('@babel/plugin-transform-classes')],
        [require('@babel/plugin-transform-arrow-functions')],
        [require('@babel/plugin-transform-spread')],
        [require('@babel/plugin-proposal-object-rest-spread')],
        [
          require('@babel/plugin-transform-template-literals'),
          {loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
        ],
        [require('@babel/plugin-transform-exponentiation-operator')],
        [require('@babel/plugin-transform-object-assign')],
        [require('@babel/plugin-transform-for-of'), {loose: true}],
        [require('@babel/plugin-transform-react-display-name')],
        [require('@babel/plugin-transform-react-jsx-source')],
      ],
    });

    return generate(
      ast,
      {
        code: true,
        comments: false,
        compact: false,
        filename: file,
        retainLines: true,
        sourceFileName: file,
        sourceMaps: true,
      },
      src,
    ).code;
  },

  getCacheKey: createCacheKeyFunction([
    __filename,
    require.resolve('metro/src/reactNativeTransformer'),
    require.resolve('@babel/core/package.json'),
  ]),
};
<|endoftext|>


<commit_before>// @flow
import * as ACTIONS from 'constants/action_types';
import { buildURI, doResolveUris, batchActions } from 'lbry-redux';
import {
  makeSelectSearchUris,
  selectSuggestions,
  makeSelectQueryWithOptions,
  selectSearchValue,
} from 'redux/selectors/search';
import debounce from 'util/debounce';
import handleFetchResponse from 'util/handle-fetch';

const DEBOUNCED_SEARCH_SUGGESTION_MS = 300;
type Dispatch = (action: any) => any;
type GetState = () => { search: SearchState };

type SearchOptions = {
  size?: number,
  from?: number,
  related_to?: string,
  nsfw?: boolean,
  isBackgroundSearch?: boolean,
};

// We can't use env's because they aren't passed into node_modules
let CONNECTION_STRING = 'https://lighthouse.lbry.com/';

export const setSearchApi = (endpoint: string) => {
  CONNECTION_STRING = endpoint.replace(/\/*$/, '/'); // exactly one slash at the end;
};

export const getSearchSuggestions = (value: string) => (dispatch: Dispatch, getState: GetState) => {
  const query = value.trim();

  // strip out any basic stuff for more accurate search results
  let searchValue = query.replace(/lbry:\/\//g, '').replace(/-/g, ' ');
  if (searchValue.includes('#')) {
    // This should probably be more robust, but I think it's fine for now
    // Remove everything after # to get rid of the claim id
    searchValue = searchValue.substring(0, searchValue.indexOf('#'));
  }

  const suggestions = selectSuggestions(getState());
  if (suggestions[searchValue]) {
    return;
  }

  fetch(`${CONNECTION_STRING}autocomplete?s=${searchValue}`)
    .then(handleFetchResponse)
    .then(apiSuggestions => {
      dispatch({
        type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
        data: {
          query: searchValue,
          suggestions: apiSuggestions,
        },
      });
    })
    .catch(() => {
      // If the fetch fails, do nothing
      // Basic search suggestions are already populated at this point
    });
};

const throttledSearchSuggestions = debounce((dispatch, query) => {
  dispatch(getSearchSuggestions(query));
}, DEBOUNCED_SEARCH_SUGGESTION_MS);

export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boolean) => (dispatch: Dispatch) => {
  dispatch({
    type: ACTIONS.UPDATE_SEARCH_QUERY,
    data: { query },
  });

  // Don't fetch new suggestions if the user just added a space
  if (!query.endsWith(' ') || !shouldSkipSuggestions) {
    throttledSearchSuggestions(dispatch, query);
  }
};

export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
  dispatch: Dispatch,
  getState: GetState
) => {
  const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
  const isBackgroundSearch = (searchOptions && searchOptions.isBackgroundSearch) || false;

  if (!query) {
    dispatch({
      type: ACTIONS.SEARCH_FAIL,
    });
    return;
  }

  const state = getState();

  let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)(state);

  // If we have already searched for something, we don't need to do anything
  const urisForQuery = makeSelectSearchUris(queryWithOptions)(state);
  if (urisForQuery && !!urisForQuery.length) {
    return;
  }

  dispatch({
    type: ACTIONS.SEARCH_START,
  });

  // If the user is on the file page with a pre-populated uri and they select
  // the search option without typing anything, searchQuery will be empty
  // We need to populate it so the input is filled on the search page
  // isBackgroundSearch means the search is happening in the background, don't update the search query
  if (!state.search.searchQuery && !isBackgroundSearch) {
    dispatch(doUpdateSearchQuery(query));
  }

  fetch(`${CONNECTION_STRING}search?${queryWithOptions}`)
    .then(handleFetchResponse)
    .then((data: Array<{ name: string, claimId: string }>) => {
      const uris = [];
      const actions = [];

      data.forEach(result => {
        if (result) {
          const { name, claimId } = result;
          const urlObj: LbryUrlObj = {};

          if (name.startsWith('@')) {
            urlObj.channelName = name;
            urlObj.channelClaimId = claimId;
          } else {
            urlObj.streamName = name;
            urlObj.streamClaimId = claimId;
          }

          const url = buildURI(urlObj);
          uris.push(url);
        }
      });

      actions.push(doResolveUris(uris));

      actions.push({
        type: ACTIONS.SEARCH_SUCCESS,
        data: {
          query: queryWithOptions,
          uris,
        },
      });
      dispatch(batchActions(...actions));
    })
    .catch(e => {
      dispatch({
        type: ACTIONS.SEARCH_FAIL,
      });
    });
};

export const doFocusSearchInput = () => (dispatch: Dispatch) =>
  dispatch({
    type: ACTIONS.SEARCH_FOCUS,
  });

export const doBlurSearchInput = () => (dispatch: Dispatch) =>
  dispatch({
    type: ACTIONS.SEARCH_BLUR,
  });

export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptions: SearchOptions) => (
  dispatch: Dispatch,
  getState: GetState
) => {
  const state = getState();
  const searchValue = selectSearchValue(state);

  dispatch({
    type: ACTIONS.UPDATE_SEARCH_OPTIONS,
    data: newOptions,
  });

  if (searchValue) {
    // After updating, perform a search with the new options
    dispatch(doSearch(searchValue, additionalOptions));
  }
};
<commit_msg>Encode autocomplete search query<commit_after>// @flow
import * as ACTIONS from 'constants/action_types';
import { buildURI, doResolveUris, batchActions } from 'lbry-redux';
import {
  makeSelectSearchUris,
  selectSuggestions,
  makeSelectQueryWithOptions,
  selectSearchValue,
} from 'redux/selectors/search';
import debounce from 'util/debounce';
import handleFetchResponse from 'util/handle-fetch';

const DEBOUNCED_SEARCH_SUGGESTION_MS = 300;
type Dispatch = (action: any) => any;
type GetState = () => { search: SearchState };

type SearchOptions = {
  size?: number,
  from?: number,
  related_to?: string,
  nsfw?: boolean,
  isBackgroundSearch?: boolean,
};

// We can't use env's because they aren't passed into node_modules
let CONNECTION_STRING = 'https://lighthouse.lbry.com/';

export const setSearchApi = (endpoint: string) => {
  CONNECTION_STRING = endpoint.replace(/\/*$/, '/'); // exactly one slash at the end;
};

export const getSearchSuggestions = (value: string) => (dispatch: Dispatch, getState: GetState) => {
  const query = value.trim();

  // strip out any basic stuff for more accurate search results
  let searchValue = query.replace(/lbry:\/\//g, '').replace(/-/g, ' ');
  if (searchValue.includes('#')) {
    // This should probably be more robust, but I think it's fine for now
    // Remove everything after # to get rid of the claim id
    searchValue = searchValue.substring(0, searchValue.indexOf('#'));
  }

  const suggestions = selectSuggestions(getState());
  if (suggestions[searchValue]) {
    return;
  }

  fetch(`${CONNECTION_STRING}autocomplete?s=${encodeURIComponent(searchValue)}`)
    .then(handleFetchResponse)
    .then(apiSuggestions => {
      dispatch({
        type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
        data: {
          query: searchValue,
          suggestions: apiSuggestions,
        },
      });
    })
    .catch(() => {
      // If the fetch fails, do nothing
      // Basic search suggestions are already populated at this point
    });
};

const throttledSearchSuggestions = debounce((dispatch, query) => {
  dispatch(getSearchSuggestions(query));
}, DEBOUNCED_SEARCH_SUGGESTION_MS);

export const doUpdateSearchQuery = (query: string, shouldSkipSuggestions: ?boolean) => (dispatch: Dispatch) => {
  dispatch({
    type: ACTIONS.UPDATE_SEARCH_QUERY,
    data: { query },
  });

  // Don't fetch new suggestions if the user just added a space
  if (!query.endsWith(' ') || !shouldSkipSuggestions) {
    throttledSearchSuggestions(dispatch, query);
  }
};

export const doSearch = (rawQuery: string, searchOptions: SearchOptions) => (
  dispatch: Dispatch,
  getState: GetState
) => {
  const query = rawQuery.replace(/^lbry:\/\//i, '').replace(/\//, ' ');
  const isBackgroundSearch = (searchOptions && searchOptions.isBackgroundSearch) || false;

  if (!query) {
    dispatch({
      type: ACTIONS.SEARCH_FAIL,
    });
    return;
  }

  const state = getState();

  let queryWithOptions = makeSelectQueryWithOptions(query, searchOptions)(state);

  // If we have already searched for something, we don't need to do anything
  const urisForQuery = makeSelectSearchUris(queryWithOptions)(state);
  if (urisForQuery && !!urisForQuery.length) {
    return;
  }

  dispatch({
    type: ACTIONS.SEARCH_START,
  });

  // If the user is on the file page with a pre-populated uri and they select
  // the search option without typing anything, searchQuery will be empty
  // We need to populate it so the input is filled on the search page
  // isBackgroundSearch means the search is happening in the background, don't update the search query
  if (!state.search.searchQuery && !isBackgroundSearch) {
    dispatch(doUpdateSearchQuery(query));
  }

  fetch(`${CONNECTION_STRING}search?${queryWithOptions}`)
    .then(handleFetchResponse)
    .then((data: Array<{ name: string, claimId: string }>) => {
      const uris = [];
      const actions = [];

      data.forEach(result => {
        if (result) {
          const { name, claimId } = result;
          const urlObj: LbryUrlObj = {};

          if (name.startsWith('@')) {
            urlObj.channelName = name;
            urlObj.channelClaimId = claimId;
          } else {
            urlObj.streamName = name;
            urlObj.streamClaimId = claimId;
          }

          const url = buildURI(urlObj);
          uris.push(url);
        }
      });

      actions.push(doResolveUris(uris));

      actions.push({
        type: ACTIONS.SEARCH_SUCCESS,
        data: {
          query: queryWithOptions,
          uris,
        },
      });
      dispatch(batchActions(...actions));
    })
    .catch(e => {
      dispatch({
        type: ACTIONS.SEARCH_FAIL,
      });
    });
};

export const doFocusSearchInput = () => (dispatch: Dispatch) =>
  dispatch({
    type: ACTIONS.SEARCH_FOCUS,
  });

export const doBlurSearchInput = () => (dispatch: Dispatch) =>
  dispatch({
    type: ACTIONS.SEARCH_BLUR,
  });

export const doUpdateSearchOptions = (newOptions: SearchOptions, additionalOptions: SearchOptions) => (
  dispatch: Dispatch,
  getState: GetState
) => {
  const state = getState();
  const searchValue = selectSearchValue(state);

  dispatch({
    type: ACTIONS.UPDATE_SEARCH_OPTIONS,
    data: newOptions,
  });

  if (searchValue) {
    // After updating, perform a search with the new options
    dispatch(doSearch(searchValue, additionalOptions));
  }
};
<|endoftext|>


<commit_before>'use strict';

var clear           = require('es5-ext/array/#/clear')
  , assign          = require('es5-ext/object/assign')
  , forEach         = require('es5-ext/object/for-each')
  , some            = require('es5-ext/object/some')
  , value           = require('es5-ext/object/valid-value')
  , isSet           = require('es6-set/is-set')
  , d               = require('d')
  , autoBind        = require('d/auto-bind')
  , genStamp        = require('time-uuid/time')
  , validDbjs       = require('dbjs/valid-dbjs')
  , DbjsEvent       = require('dbjs/_setup/event')
  , validDbjsObject = require('dbjs/valid-dbjs-object')
  , serializeKey    = require('dbjs/_setup/serialize/key')

  , create = Object.create, getPrototypeOf = Object.getPrototypeOf
  , SyncRoot, SyncMaster, propagateComputedItem
  , resolveTargetValue, resolveTargetObject;

resolveTargetObject = function (db, objectId) {
	var object = db.objects.unserialize(objectId);
	if ((object._kind_ === 'descriptor') && object.nested) return object.object._get_(object._sKey_);
	return object;
};
resolveTargetValue = function (db, objectId, sKey) {
	return resolveTargetObject(db, objectId)._get_(sKey);
};
propagateComputedItem = function (stamp, baseId, value, key) {
	new DbjsEvent(this.base.db.objects.unserialize(baseId + '*' + serializeKey(key)), value,
		stamp); //jslint: ignore
};

SyncRoot = function (db, propertyName) {
	this.db = db;
	this.map = create(null);
	this.masterMap = create(null);
	this.propertyName = propertyName;
};

Object.defineProperties(SyncRoot.prototype, {
	sync: d(function (object) {
		validDbjsObject(object);
		if (this.masterMap[object.__id__]) return;
		this.masterMap[object.__id__] = true;
		this._syncMaster(object);
	}),
	_syncMaster: d(function (object) {
		if (this.map[object.__id__]) return;
		this.map[object.__id__] = true;
		this.map[object.__id__] = new SyncMaster(object, this);
	}),
	_unsyncMaster: d(function (object) {
		if (this.masterMap[object.__id__]) return;
		if (some(this.map, function (sync) {
				if (sync === true) return;
				if (sync.object === object) return;
				if (sync.descendants[object.__id__]) return true;
			})) {
			return;
		}
		this.map[object.__id__].remove();
	})
});

SyncMaster = function (object, base) {
	this.object = object;
	this.base = base;
	this.namesToSync = create(null);
	this.observed = [];
	this.descendants = create(null);
	this.extValuesMap = create(null);
	object.on('turn', this.onTurn);
	this.onTurn(object._lastOwnEvent_);
};
Object.defineProperties(SyncMaster.prototype, assign({
	initialized: d(false),
	initialize: d(function () {
		this.initialized = true;
		this.syncProperties(this.object);
		this.object.on('update', this.onDbEvent);
	}),
	syncProperties: d(function (object) {
		var sKey, desc, baseDesc, observable;

		for (sKey in object.__descriptors__) {
			desc = object.__descriptors__[sKey];
			if (desc.reverse != null) continue;
			if (desc.nested) {
				this.syncProperties(object.get(desc.key));
				continue;
			}
			if (desc[this.base.propertyName] === undefined) continue;
			baseDesc = desc;
			while (!baseDesc.hasOwnProperty(this.base.propertyName)) baseDesc = getPrototypeOf(baseDesc);
			if (!baseDesc.master.isPrototypeOf(object.master)) continue;

			// Export!
			if (!desc._resolveValueGetter_()) {

				// Static
				this.namesToSync[desc.__valueId__] = true;
				if (desc.multiple) {
					object._forEachOwnItem_(this.syncObjectDirectly, this);
					continue;
				}
				if (desc.object !== object) continue;
				this.syncObjectDirectly(desc);
				continue;
			}

			// Computable
			if (desc.multiple) {
				this.observed.push(observable = object._get_(sKey));
				this.syncComputedSet(observable,
					resolveTargetValue(this.base.db, object.__id__, sKey),
					object._getPropertyLastEvent_(sKey));
				observable.on('change', this.onSetChangeEvent);
				continue;
			}
			this.observed.push(observable = object._getObservable_(sKey));
			this.syncComputedValue(observable, object._getPropertyLastEvent_(sKey));
			observable.on('change', this.onChangeEvent);
		}
	}),
	syncObjectDirectly: d(function (object) {
		var event = object._lastOwnEvent_;
		if (!event) return;
		this.syncEventDirectly(event);
	}),
	syncExternal: d(function (path, object, isMultiple, multipleValue) {
		var id, prevId;
		object = object.master;
		if (object === this.object) return;
		if (typeof object === 'function') return;
		if (object._kind_ !== 'object') return;
		if (object.constructor.prototype === object) return;
		id = object.__id__;
		if (isMultiple) {
			if (multipleValue) {
				if (!this.extValuesMap[path]) this.extValuesMap[path] = create(null);
				if (this.extValuesMap[path][id]) return;
				this.extValuesMap[path][id] = true;
				if (!this.descendants[id]) {
					this.descendants[id] = 0;
					this.base._syncMaster(object);
				}
				++this.descendants[id];
				return;
			}
			if (!this.extValuesMap[path]) return;
			if (!this.extValuesMap[path][id]) return;
			delete this.extValuesMap[path][id];
			if (!--this.descendants[id]) this.base._unsyncMaster(object);
			return;
		}
		prevId = this.extValuesMap[path];
		if (prevId && (!--this.descendants[prevId])) {
			this.base._unsyncMaster(object.database.objects.getById(prevId));
		}
		this.extValuesMap[path] = id;
		if (!this.descendants[id]) {
			this.descendants[id] = 0;
			this.base._syncMaster(object);
		}
		++this.descendants[id];
	}),
	syncEventDirectly: d(function (event) {
		var value = event.value, object = event.object, targetEvent;
		if (object._kind_ === 'descriptor') {
			if (value && value.hasOwnProperty('__id__')) {
				this.syncExternal(object.__valueId__, value);
				value = this.base.db.objects.getById(value.__id__);
			}
		} else if (object._kind_ === 'item') {
			if (object.key.hasOwnProperty('__id__')) {
				this.syncExternal(object.object.__id__ + '/' + object._pSKey_, object.key, true, value);
			}
		} else if (object._kind_ === 'object') {
			if (value && value.hasOwnProperty('__id__')) {
				value = this.base.db.objects.getById(value.__id__);
			}
		}
		object = this.base.db.objects.unserialize(event.object.__valueId__, value);
		targetEvent = object._lastOwnEvent_;
		if (targetEvent && (targetEvent.stamp >= event.stamp)) return;
		new DbjsEvent(object, value, event.stamp); //jslint: ignore
	}),
	syncComputedValue: d(function (observable, event) {
		var source = observable.value
		  , targetObject = resolveTargetObject(this.base.db, observable.object.__id__)
		  , target = targetObject._get_(observable.__sKey__)
		  , stamp, targetLastEvent;
		if (source === target) return;
		if ((target == null) && (source == null)) return;
		if (source && source.hasOwnProperty('__id__')) this.syncExternal(observable.dbId, source);
		stamp = (event && event.stamp) || genStamp();
		targetLastEvent = targetObject._getOwnDescriptor_(observable.__sKey__)._lastOwnEvent_;
		if (targetLastEvent && (targetLastEvent.stamp >= stamp)) stamp = targetLastEvent.stamp + 1;
		new DbjsEvent(targetObject._getOwnDescriptor_(observable.__sKey__),
			source, stamp); //jslint: ignore
	}),
	syncComputedSet: d(function (source, target, event) {
		var sourceIterator, targetIterator, item, isDifferent, stamp;

		if (source.size === target.size) {
			if (!source.size) return;
			sourceIterator = source.values();
			targetIterator = target.values();
			item = sourceIterator.next();
			while (!item.done) {
				if (item.value !== targetIterator.next().value) {
					isDifferent = true;
					break;
				}
				item = sourceIterator.next();
			}
			if (sourceIterator._destroy) sourceIterator._destroy();
			if (targetIterator._destroy) targetIterator._destroy();
			if (!isDifferent) return;
		}
		stamp = (event && event.stamp) || genStamp();
		forEach(target.__setData__, function (item) {
			var event = item._lastOwnEvent_;
			if (!event) return;
			if (event.stamp >= stamp) stamp = event.stamp + 1;
		});
		target.forEach(function (item) {
			if (!source.has(item)) {
				if (item.hasOwnProperty('__id__')) {
					this.syncExternal(target.dbId, source.database.objects.getById(item.__id__),
						true, undefined);
				}
				propagateComputedItem.call(this, stamp++, target.dbId, undefined, item);
			}
		}, this);
		source.forEach(function (item) {
			if (item.hasOwnProperty('__id__')) this.syncExternal(target.dbId, item, true, true);
			propagateComputedItem.call(this, stamp++, target.dbId, true, item);
		}, this);
	}),
	destroy: d(function () {
		this.object.off('update', this.onDbEvent);
		this.observed.forEach(function (observable) {
			observable.off('change', isSet(observable) ? this.onSetChangeEvent : this.onChangeEvent);
		}, this);
		clear.call(this.observed);
	}),
	remove: d(function () {
		this.destroy();
		delete this.base.map[this.object.__id__];
		delete this.base.masterMap[this.object.__id__];
		this.object.off('turn', this.onTurn);
	})
}, autoBind({
	onTurn: d(function (event) {
		this.syncEventDirectly(event);
		if (this.object.constructor.__id__ === 'Base') {
			if (!this.initialized) return;
			this.destroy();
			return;
		}
		if (this.initialized) return;
		this.initialize();
	}),
	onDbEvent: d(function (event) {
		var object = event.object;
		switch (object._kind_) {
		case 'descriptor':
			if (!this.namesToSync[object.__valueId__]) return;
			break;
		case 'item':
			if (!this.namesToSync[object.object.__id__ + '/' + object._pSKey_]) return;
			break;
		case 'object':
			return;
		case 'sub-descriptor':
			return;
		}
		this.syncEventDirectly(event);
	}),
	onChangeEvent: d(function (event) { this.syncComputedValue(event.target, event.dbjs); }),
	onSetChangeEvent: d(function (event) {
		this.syncComputedSet(event.target, resolveTargetValue(this.base.db,
			event.target.object.__id__, event.target.__sKey__), event.dbjs);
	})
})));

module.exports = function (targetDb, propertyName) {
	var sync = new SyncRoot(validDbjs(targetDb), value(propertyName));
	return sync.sync.bind(sync);
};
<commit_msg>Assure that only given property items are copied<commit_after>'use strict';

var clear           = require('es5-ext/array/#/clear')
  , assign          = require('es5-ext/object/assign')
  , forEach         = require('es5-ext/object/for-each')
  , some            = require('es5-ext/object/some')
  , value           = require('es5-ext/object/valid-value')
  , isSet           = require('es6-set/is-set')
  , d               = require('d')
  , autoBind        = require('d/auto-bind')
  , genStamp        = require('time-uuid/time')
  , validDbjs       = require('dbjs/valid-dbjs')
  , DbjsEvent       = require('dbjs/_setup/event')
  , validDbjsObject = require('dbjs/valid-dbjs-object')
  , serializeKey    = require('dbjs/_setup/serialize/key')

  , create = Object.create, getPrototypeOf = Object.getPrototypeOf
  , hasOwnProperty = Object.prototype.hasOwnProperty
  , SyncRoot, SyncMaster, propagateComputedItem
  , resolveTargetValue, resolveTargetObject;

resolveTargetObject = function (db, objectId) {
	var object = db.objects.unserialize(objectId);
	if ((object._kind_ === 'descriptor') && object.nested) return object.object._get_(object._sKey_);
	return object;
};
resolveTargetValue = function (db, objectId, sKey) {
	return resolveTargetObject(db, objectId)._get_(sKey);
};
propagateComputedItem = function (stamp, baseId, value, key) {
	new DbjsEvent(this.base.db.objects.unserialize(baseId + '*' + serializeKey(key)), value,
		stamp); //jslint: ignore
};

SyncRoot = function (db, propertyName) {
	this.db = db;
	this.map = create(null);
	this.masterMap = create(null);
	this.propertyName = propertyName;
};

Object.defineProperties(SyncRoot.prototype, {
	sync: d(function (object) {
		validDbjsObject(object);
		if (this.masterMap[object.__id__]) return;
		this.masterMap[object.__id__] = true;
		this._syncMaster(object);
	}),
	_syncMaster: d(function (object) {
		if (this.map[object.__id__]) return;
		this.map[object.__id__] = true;
		this.map[object.__id__] = new SyncMaster(object, this);
	}),
	_unsyncMaster: d(function (object) {
		if (this.masterMap[object.__id__]) return;
		if (some(this.map, function (sync) {
				if (sync === true) return;
				if (sync.object === object) return;
				if (sync.descendants[object.__id__]) return true;
			})) {
			return;
		}
		this.map[object.__id__].remove();
	})
});

SyncMaster = function (object, base) {
	this.object = object;
	this.base = base;
	this.namesToSync = create(null);
	this.observed = [];
	this.descendants = create(null);
	this.extValuesMap = create(null);
	object.on('turn', this.onTurn);
	this.onTurn(object._lastOwnEvent_);
};
Object.defineProperties(SyncMaster.prototype, assign({
	initialized: d(false),
	initialize: d(function () {
		this.initialized = true;
		this.syncProperties(this.object);
		this.object.on('update', this.onDbEvent);
	}),
	syncProperties: d(function (object) {
		var sKey, desc, baseDesc, observable;

		for (sKey in object.__descriptors__) {
			desc = object.__descriptors__[sKey];
			if (desc.reverse != null) continue;
			if (desc.nested) {
				this.syncProperties(object.get(desc.key));
				continue;
			}
			if (desc[this.base.propertyName] === undefined) continue;
			baseDesc = desc;
			while (!baseDesc.hasOwnProperty(this.base.propertyName)) baseDesc = getPrototypeOf(baseDesc);
			if (!baseDesc.master.isPrototypeOf(object.master)) continue;

			// Export!
			if (!desc._resolveValueGetter_()) {

				// Static
				this.namesToSync[desc.__valueId__] = true;
				if (desc.multiple) {
					if (!object.hasOwnProperty('__multiples__')) continue;
					if (!hasOwnProperty.call(object.__multiples__, sKey)) continue;
					forEach(object.__multiples__[sKey], this.syncObjectDirectly, this);
					continue;
				}
				if (desc.object !== object) continue;
				this.syncObjectDirectly(desc);
				continue;
			}

			// Computable
			if (desc.multiple) {
				this.observed.push(observable = object._get_(sKey));
				this.syncComputedSet(observable,
					resolveTargetValue(this.base.db, object.__id__, sKey),
					object._getPropertyLastEvent_(sKey));
				observable.on('change', this.onSetChangeEvent);
				continue;
			}
			this.observed.push(observable = object._getObservable_(sKey));
			this.syncComputedValue(observable, object._getPropertyLastEvent_(sKey));
			observable.on('change', this.onChangeEvent);
		}
	}),
	syncObjectDirectly: d(function (object) {
		var event = object._lastOwnEvent_;
		if (!event) return;
		this.syncEventDirectly(event);
	}),
	syncExternal: d(function (path, object, isMultiple, multipleValue) {
		var id, prevId;
		object = object.master;
		if (object === this.object) return;
		if (typeof object === 'function') return;
		if (object._kind_ !== 'object') return;
		if (object.constructor.prototype === object) return;
		id = object.__id__;
		if (isMultiple) {
			if (multipleValue) {
				if (!this.extValuesMap[path]) this.extValuesMap[path] = create(null);
				if (this.extValuesMap[path][id]) return;
				this.extValuesMap[path][id] = true;
				if (!this.descendants[id]) {
					this.descendants[id] = 0;
					this.base._syncMaster(object);
				}
				++this.descendants[id];
				return;
			}
			if (!this.extValuesMap[path]) return;
			if (!this.extValuesMap[path][id]) return;
			delete this.extValuesMap[path][id];
			if (!--this.descendants[id]) this.base._unsyncMaster(object);
			return;
		}
		prevId = this.extValuesMap[path];
		if (prevId && (!--this.descendants[prevId])) {
			this.base._unsyncMaster(object.database.objects.getById(prevId));
		}
		this.extValuesMap[path] = id;
		if (!this.descendants[id]) {
			this.descendants[id] = 0;
			this.base._syncMaster(object);
		}
		++this.descendants[id];
	}),
	syncEventDirectly: d(function (event) {
		var value = event.value, object = event.object, targetEvent;
		if (object._kind_ === 'descriptor') {
			if (value && value.hasOwnProperty('__id__')) {
				this.syncExternal(object.__valueId__, value);
				value = this.base.db.objects.getById(value.__id__);
			}
		} else if (object._kind_ === 'item') {
			if (object.key.hasOwnProperty('__id__')) {
				this.syncExternal(object.object.__id__ + '/' + object._pSKey_, object.key, true, value);
			}
		} else if (object._kind_ === 'object') {
			if (value && value.hasOwnProperty('__id__')) {
				value = this.base.db.objects.getById(value.__id__);
			}
		}
		object = this.base.db.objects.unserialize(event.object.__valueId__, value);
		targetEvent = object._lastOwnEvent_;
		if (targetEvent && (targetEvent.stamp >= event.stamp)) return;
		new DbjsEvent(object, value, event.stamp); //jslint: ignore
	}),
	syncComputedValue: d(function (observable, event) {
		var source = observable.value
		  , targetObject = resolveTargetObject(this.base.db, observable.object.__id__)
		  , target = targetObject._get_(observable.__sKey__)
		  , stamp, targetLastEvent;
		if (source === target) return;
		if ((target == null) && (source == null)) return;
		if (source && source.hasOwnProperty('__id__')) this.syncExternal(observable.dbId, source);
		stamp = (event && event.stamp) || genStamp();
		targetLastEvent = targetObject._getOwnDescriptor_(observable.__sKey__)._lastOwnEvent_;
		if (targetLastEvent && (targetLastEvent.stamp >= stamp)) stamp = targetLastEvent.stamp + 1;
		new DbjsEvent(targetObject._getOwnDescriptor_(observable.__sKey__),
			source, stamp); //jslint: ignore
	}),
	syncComputedSet: d(function (source, target, event) {
		var sourceIterator, targetIterator, item, isDifferent, stamp;

		if (source.size === target.size) {
			if (!source.size) return;
			sourceIterator = source.values();
			targetIterator = target.values();
			item = sourceIterator.next();
			while (!item.done) {
				if (item.value !== targetIterator.next().value) {
					isDifferent = true;
					break;
				}
				item = sourceIterator.next();
			}
			if (sourceIterator._destroy) sourceIterator._destroy();
			if (targetIterator._destroy) targetIterator._destroy();
			if (!isDifferent) return;
		}
		stamp = (event && event.stamp) || genStamp();
		forEach(target.__setData__, function (item) {
			var event = item._lastOwnEvent_;
			if (!event) return;
			if (event.stamp >= stamp) stamp = event.stamp + 1;
		});
		target.forEach(function (item) {
			if (!source.has(item)) {
				if (item.hasOwnProperty('__id__')) {
					this.syncExternal(target.dbId, source.database.objects.getById(item.__id__),
						true, undefined);
				}
				propagateComputedItem.call(this, stamp++, target.dbId, undefined, item);
			}
		}, this);
		source.forEach(function (item) {
			if (item.hasOwnProperty('__id__')) this.syncExternal(target.dbId, item, true, true);
			propagateComputedItem.call(this, stamp++, target.dbId, true, item);
		}, this);
	}),
	destroy: d(function () {
		this.object.off('update', this.onDbEvent);
		this.observed.forEach(function (observable) {
			observable.off('change', isSet(observable) ? this.onSetChangeEvent : this.onChangeEvent);
		}, this);
		clear.call(this.observed);
	}),
	remove: d(function () {
		this.destroy();
		delete this.base.map[this.object.__id__];
		delete this.base.masterMap[this.object.__id__];
		this.object.off('turn', this.onTurn);
	})
}, autoBind({
	onTurn: d(function (event) {
		this.syncEventDirectly(event);
		if (this.object.constructor.__id__ === 'Base') {
			if (!this.initialized) return;
			this.destroy();
			return;
		}
		if (this.initialized) return;
		this.initialize();
	}),
	onDbEvent: d(function (event) {
		var object = event.object;
		switch (object._kind_) {
		case 'descriptor':
			if (!this.namesToSync[object.__valueId__]) return;
			break;
		case 'item':
			if (!this.namesToSync[object.object.__id__ + '/' + object._pSKey_]) return;
			break;
		case 'object':
			return;
		case 'sub-descriptor':
			return;
		}
		this.syncEventDirectly(event);
	}),
	onChangeEvent: d(function (event) { this.syncComputedValue(event.target, event.dbjs); }),
	onSetChangeEvent: d(function (event) {
		this.syncComputedSet(event.target, resolveTargetValue(this.base.db,
			event.target.object.__id__, event.target.__sKey__), event.dbjs);
	})
})));

module.exports = function (targetDb, propertyName) {
	var sync = new SyncRoot(validDbjs(targetDb), value(propertyName));
	return sync.sync.bind(sync);
};
<|endoftext|>


<commit_before>describe('Conway Game of Life main controller', function() {
    var ctrl,
        scope;

    beforeEach(function() {
        module('ConwayGameOfLife');

        inject(function($rootScope, $controller) {
            scope = $rootScope.$new();
            ctrl = $controller('MainCtrl', {
                $scope: scope
            });
        });
    });

    it('should exist', function() {
        expect(ctrl).toBeTruthy();
    });

    it('should default grid size to four', function() {
        expect(scope.gridsize).toBe(4);
    });

    it('should initially hide the "tick" button', function() {
        expect(scope.hideTickButton).toBe(true);
    });

    it('should initially hide the "terminal state reached" message', function() {
        expect(scope.hideTerminalStateMessage).toBe(true);
    });
});
<commit_msg>Added existence tests for six $scope functions<commit_after>describe('Conway Game of Life main controller', function() {
    var ctrl,
        scope;

    beforeEach(function() {
        module('ConwayGameOfLife');

        inject(function($rootScope, $controller) {
            scope = $rootScope.$new();
            ctrl = $controller('MainCtrl', {
                $scope: scope
            });
        });
    });

    it('should exist', function() {
        expect(ctrl).toBeTruthy();
    });

    it('should default grid size to four', function() {
        expect(scope.gridsize).toBe(4);
    });

    it('should initially hide the "tick" button', function() {
        expect(scope.hideTickButton).toBe(true);
    });

    it('should initially hide the "terminal state reached" message', function() {
        expect(scope.hideTerminalStateMessage).toBe(true);
    });

    describe('$scope.makeNewBoardOfSize function', function() {
        it('should exist', function() {
            expect(scope.makeNewBoardOfSize).toBeTruthy();
        });
    });

    describe('$scope.tick function', function() {
        it('should exist', function() {
            expect(scope.tick).toBeTruthy();
        });
    });

    describe('$scope.deadCell function', function() {
        it('should exist', function() {
            expect(scope.deadCell).toBeTruthy();
        });
    });

    describe('$scope.livingCell function', function() {
        it('should exist', function() {
            expect(scope.livingCell).toBeTruthy();
        });
    });

    describe('$scope.generateInitialGrid function', function() {
        it('should exist', function() {
            expect(scope.generateInitialGrid).toBeTruthy();
        });
    });

    describe('$scope.numberOfLivingNeighbors function', function() {
        it('should exist', function() {
            expect(scope.numberOfLivingNeighbors).toBeTruthy();
        });
    });
});
<|endoftext|>


<commit_before>/*#ifndef(UMD)*/
"use strict";
/*jshint -W098*/ // This is a constant list, they won't be used in here
/*jshint -W079*/ // Globals are also copied here
/*#endif*/

/*global gpfSourcesPath*/ // Global source path
/*global _gpfVersion*/ // GPF version
/*global _gpfHost*/ // Host type
/*global _gpfContext*/ // Main context object
/*global _gpfResolveScope*/ // Translate the parameter into a valid scope
/*global _gpfInNode*/ // The current host is a nodeJS like
/*global _gpfInBrowser*/ // The current host is a browser like
/*global _gpfWebWindow*/ // Browser window object
/*global _gpfWebDocument*/ // Browser document object
/*global _gpfWebHead*/ // Browser head tag
/*global _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*global _gpfNodeFS*/ // Node FS module
/*global _gpfFSRead*/ // Phantom/Node File System read text file method (boot)
/*global _gpfEmptyFunc*/ // An empty function
/*global _gpfFalseFunc*/ // An empty function returning false
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfAlpha*/ // Letters (lowercase)
/*global _gpfALPHA*/ // Letters (uppercase)
/*global _gpfDigit*/ // Digits
/*global _gpfArraySlice*/ // Shortcut on Array.prototype.slice

var
/*#ifdef(RELEASE)*/
    _gpfTypeofBoolean = "boolean",
    _gpfTypeofFunction = "function",
    _gpfTypeofNumber = "number",
    _gpfTypeofObject = "object",
    _gpfTypeofString = "string",
    _gpfTypeofUndefined = "undefined",
    _gpfUndefined = void 0,
    _gpfTrue = !!1,
    _gpfFalse = !_gpfTrue,
    _gpfNull = null,

    /*#define "boolean" _gpfTypeofBoolean*/
    /*#define "function" _gpfTypeofFunction*/
    /*#define "number" _gpfTypeofNumber*/
    /*#define "object" _gpfTypeofObject*/
    /*#define "string" _gpfTypeofString*/
    /*#define "undefined" _gpfTypeofUndefined*/
    /*#define undefined _gpfUndefined*/
    /*#define true _gpfTrue*/
    /*#define false _gpfFalse*/
    /*#define null _gpfNull*/
/*#endif*/

    // https://github.com/jshint/jshint/issues/525
    _GpfFunc = Function, // avoid JSHint error

    /**
     * An empty function
     *
     * @private
     */
    _gpfEmptyFunc = function () {},

    /**
     * An empty function returning false
     *
     * @result {Boolean} False
     * @private
     */
    _gpfFalseFunc = function () {
        return false;
    },

    /**
     * Create a new function using the source
     * In DEBUG mode, it catches any error to signal the problem
     *
     * @param {String} source
     * @returns {Function}
     * @private
     */
    _gpfFunc = function (source) {
/*#ifdef(DEBUG)*/
        try {
/*#endif*/
            gpf.ASSERT("string" === typeof source && source.length,
                "Source expected (or use _gpfEmptyFunc)");
            return new _GpfFunc(source);
/*#ifdef(DEBUG)*/
        } catch (e) {
            console.error("An exception occurred compiling:\r\n" + source);
            return null;
        }
/*#endif*/
    },

    /**
     * Letters (lowercase)
     *
     * @type {string}
     * @private
     */
    _gpfAlpha = "abcdefghijklmnopqrstuvwxyz",

    /**
     * Letters (uppercase)
     *
     * @type {string}
     * @private
     */
    _gpfALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",

    /**
     * Digits
     *
     * @type {string}
     * @private
     */
    _gpfDigit = "0123456789";

/*#ifndef(UMD)*/
// Mandatory to support boot loading in a browser (removed when UMD is used)
gpf._constants = true;
/*#endif*/<commit_msg>New exports<commit_after>/*#ifndef(UMD)*/
"use strict";
/*jshint -W098*/ // This is a constant list, they won't be used in here
/*jshint -W079*/ // Globals are also copied here
/*#endif*/

/*global gpfSourcesPath*/ // Global source path
/*global _gpfVersion*/ // GPF version
/*global _gpfHost*/ // Host type
/*global _gpfContext*/ // Main context object
/*global _gpfResolveScope*/ // Translate the parameter into a valid scope
/*global _gpfIsArrayLike*/ // Return true if the parameter looks like an array
/*global _gpfInNode*/ // The current host is a nodeJS like
/*global _gpfInBrowser*/ // The current host is a browser like
/*global _gpfWebWindow*/ // Browser window object
/*global _gpfWebDocument*/ // Browser document object
/*global _gpfWebHead*/ // Browser head tag
/*global _gpfMsFSO*/ // Scripting.FileSystemObject activeX
/*global _gpfNodeFS*/ // Node FS module
/*global _gpfFSRead*/ // Phantom/Node File System read text file method (boot)
/*global _gpfEmptyFunc*/ // An empty function
/*global _gpfIgnore*/ // Helper to remove unused parameter warning
/*global _gpfFalseFunc*/ // An empty function returning false
/*global _gpfFunc*/ // Create a new function using the source
/*global _gpfAlpha*/ // Letters (lowercase)
/*global _gpfALPHA*/ // Letters (uppercase)
/*global _gpfDigit*/ // Digits
/*global _gpfArraySlice*/ // Shortcut on Array.prototype.slice
/*global _gpfDefer*/ // Defer the execution of the callback

var
/*#ifdef(RELEASE)*/
    _gpfTypeofBoolean = "boolean",
    _gpfTypeofFunction = "function",
    _gpfTypeofNumber = "number",
    _gpfTypeofObject = "object",
    _gpfTypeofString = "string",
    _gpfTypeofUndefined = "undefined",
    _gpfUndefined = void 0,
    _gpfTrue = !!1,
    _gpfFalse = !_gpfTrue,
    _gpfNull = null,

    /*#define "boolean" _gpfTypeofBoolean*/
    /*#define "function" _gpfTypeofFunction*/
    /*#define "number" _gpfTypeofNumber*/
    /*#define "object" _gpfTypeofObject*/
    /*#define "string" _gpfTypeofString*/
    /*#define "undefined" _gpfTypeofUndefined*/
    /*#define undefined _gpfUndefined*/
    /*#define true _gpfTrue*/
    /*#define false _gpfFalse*/
    /*#define null _gpfNull*/
/*#endif*/

    // https://github.com/jshint/jshint/issues/525
    _GpfFunc = Function, // avoid JSHint error

    /**
     * An empty function
     *
     * @private
     */
    _gpfEmptyFunc = function () {},

    /**
     * Helper to ignore unused parameter
     *
     * @param {*} param
     * @private
     */
    _gpfIgnore = _gpfEmptyFunc,

    /**
     * An empty function returning false
     *
     * @result {Boolean} False
     * @private
     */
    _gpfFalseFunc = function () {
        return false;
    },

    /**
     * Create a new function using the source
     * In DEBUG mode, it catches any error to signal the problem
     *
     * @param {String} source
     * @returns {Function}
     * @private
     */
    _gpfFunc = function (source) {
/*#ifdef(DEBUG)*/
        try {
/*#endif*/
            gpf.ASSERT("string" === typeof source && source.length,
                "Source expected (or use _gpfEmptyFunc)");
            return new _GpfFunc(source);
/*#ifdef(DEBUG)*/
        } catch (e) {
            console.error("An exception occurred compiling:\r\n" + source);
            return null;
        }
/*#endif*/
    },

    /**
     * Letters (lowercase)
     *
     * @type {string}
     * @private
     */
    _gpfAlpha = "abcdefghijklmnopqrstuvwxyz",

    /**
     * Letters (uppercase)
     *
     * @type {string}
     * @private
     */
    _gpfALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",

    /**
     * Digits
     *
     * @type {string}
     * @private
     */
    _gpfDigit = "0123456789";

/*#ifndef(UMD)*/
// Mandatory to support boot loading in a browser (removed when UMD is used)
gpf._constants = true;
/*#endif*/<|endoftext|>