<commit_before>$.ajaxSetup ({
    cache: false
});
var ajaxLoadImg = "";
var ajaxLoadImgRev = "";
var collectionIds = []
var currentUserInputValue = ""

/*****************************************************************************
 * create collection page
 ****************************************************************************/

exampleStrings = {
    paste_input:"doi:10.123/somejournal/123\nhttp://www.example.com",
    crossref_input: "Watson:  A Structure for Deoxyribose Nucleic Acid\nGeertz: Deep play: Notes on the Balinese cockfight",
    name: "My Collection"
}

inputExamplesIClickHandler = function(thisInput) {

}

flatten = function(idsArr) {
    // flattens id values that are themselves arrays (like github)
    var aliases = [];
    numIds = idsArr.length;
    for (var i=0; i<numIds; i++ ) {
        var id = idsArr[i][1]
        var namespace = idsArr[i][0]
        if( Object.prototype.toString.call( id ) === '[object Array]' ) {
            var strVal = id.join(",")
        }
        else {
            var strVal = id
        }
        aliases.push([namespace, id])
    }
    return(aliases)
}

addCollectionIds = function(idsArr, $this) {
    var startingCollectionLength = collectionIds.length
    var newIds = flatten(idsArr);

    // make an object with the unique key values
    var uniqueNamespaceIdPairs = {}
    for  (var i=0; i<collectionIds.length; i++){
        var namespaceIdPair = collectionIds[i].join(":")
        uniqueNamespaceIdPairs[namespaceIdPair] = 1
    }
    console.log(uniqueNamespaceIdPairs)

    for (var i=0; i < newIds.length; i++){
        var newNamespaceIdPair = newIds[i].join(":")
        if (!uniqueNamespaceIdPairs[newNamespaceIdPair]) {
            collectionIds.push(newIds[i])
        }
    }
    $("span.loading").remove()

    // how many items are in the new collection now?
    var endingCollectionLength = collectionIds.length;
    numIdsAdded = endingCollectionLength - startingCollectionLength;
    $("#artcounter span.count").html(endingCollectionLength);
    if (numIdsAdded) {
        $this.siblings("span.added").remove()
        $this.after(""+numIdsAdded+" items added.")
        $this.siblings("span.added")
            .find("span.count")
                .css({color: "#ff4e00"})
                .animate({color: "#555555"}, 1000)

    }
    return true;

}

// puts the textarea-entered ids in a format that addcollectionIds likes
parseTextareaArtifacts = function(str) {
    var ids = str.split("\n");
    var ret = [];
    for (i=0; i<ids.length; i++){
        var artifact = [];
        var thisId = ids[i];
        if (thisId.indexOf(":") > 0) {
            artifact[0] = thisId.split(':')[0]; // namespace
            artifact[1] = thisId.substr(artifact[0].length + 1) // id

            // handle urls:
            if (artifact[0] == "http"){
                artifact[0] = "url";
                artifact[1] = thisId
            }
        }
        else {
            if (thisId.length > 0) {
                // handle dois entered without the doi prefix
                if (thisId.substring(0,3) == "10.") {
                    artifact[0] = "doi"
                } else {
                   artifact[0] = "unknown"
                }
                artifact[1] = thisId
            }
        }
        if (typeof artifact[1] != "undefined") {
            ret.push(artifact);
        }
    }
    return ret;
}
userInputHandler = function($this, prevValue) {
    $this.blur(function(){

    });

}

upload_bibtex = function(files) {
    var fileInput = $("li #input_bibtex")[0];
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('file', file);
    $("li #input_bibtex").siblings("span.added").remove()
    $("li #input_bibtex").after(""+ajaxLoadImg+"");

    $.ajax({
            url: "http://"+api_root+'/provider/bibtex/memberitems',
            type: "POST",
            processData: false,
            contentType: false,
            data: formData,
            success:  function(response,status,xhr){
                addCollectionIds(response, $("li #input_bibtex"))
        }});
    }

createCollectionInit = function(){

    $("li textarea, input#name").each(function(){
        $(this).val(exampleStrings[this.id])
    })
    $("li input, li textarea, input#name")
    .focus(function(){
        currentUserInputValue = $(this).val();
        $(this).removeClass("no-input-yet")

        // hid the example strings if they're still up.
        if (currentUserInputValue == exampleStrings[this.id]) {
            $(this).val("")
        }
    })
    .blur(function(){
        $this = $(this)
        if ($this.val() == "") {
            $this.addClass("no-input-yet")
            $this.val(exampleStrings[this.id])
            return false;
        }
        else if ($this.val() == currentUserInputValue) {
            return false;
        }

        if ($this.attr("id") == "paste_input") {
            newIds = parseTextareaArtifacts($(this).val());
            addCollectionIds(newIds, $(this))
        }
        else {
            var idStrParts = $(this).attr("id").split('_');
            var providerName = idStrParts[0];

            if (providerName == "crossref") { // hack, should generalize for all textareas
                var providerTypeQuery = "&type=import"
                var pipeVal = $this.val().replace(":", "|");
                var providerIdQuery = "?query=" + escape(pipeVal);
            } else {
                var providerTypeQuery = "&type=" + $this.attr("name");
                var providerIdQuery = "?query=" + escape($this.val());
            }
            $(this).siblings("span.added").remove()
            $(this).after(""+ajaxLoadImg+"");
            $.get("http://"+api_root+"/provider/"+providerName+"/memberitems"+providerIdQuery+providerTypeQuery, function(response,status,xhr){
                addCollectionIds(response, $this)
            }, "json");

        }
    })

    // creating a collection by submitting the object IDs from the homepage
    $("#id-form").submit(function(){

        // make sure the user input something at all
        if (collectionIds.length == 0) {
            alert("Looks like you haven't added any research objects to the collection yet.")
            return false;

        // created items and put them in a collection, then redirect to
        // the collection report page:
        } else {
            // first we upload the new items and get tiids back.
            console.log("adding new items.")
            $("#go-button").replaceWith(""+ajaxLoadImg+"")
            $.ajax({
                url: "http://"+api_root+'/items',
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify(collectionIds),
                success: function(returnedTiids){
                    // make a new collection, populated by our freshly-minted tiids
                    console.log("items created. making collection.")
                    var requestObj = {
                        title: $('#name').val(),
                        items: returnedTiids
                    }

                    $.ajax({
                        url: "http://"+api_root+'/collection',
                        type: "POST",
                        dataType: "json",
                        contentType: "application/json; charset=utf-8",
                        data:  JSON.stringify(requestObj),
                        success: function(returnedCollection){

                            // we've created the items and the collection; our
                            // work here is done.
                            console.log(returnedCollection)
                            location.href = "/collection/" +returnedCollection.id;
                        }
                    });
                }
            });
            return false;
        }
    });
}

/*****************************************************************************
 * report page
 ****************************************************************************/

function renderItemBiblio(biblio, url) {
    var html = ""

    biblio.url = url
    biblio.title = biblio.title || "no title"
    if (biblio.create_date) {
        biblio.year = biblio.create_date.slice(0,4)
    }

    var templateName = "biblio_" + biblio.genre
    return ich[templateName](biblio, true)
}

getLatestTs = function(metricSnaps) {
    var latestTs = "1999-01-01T00:00:00.000000"
    for (ts in metricSnaps) {
        if (ts > latestTs) {
            latestTs = ts
        }
    }
    return latestTs
}

function sortByMetricValueDesc(metric1, metric2){
  if (metric1.value < metric2.value)
     return 1;
  if (metric1.value > metric2.value)
    return -1;
  return 0;
}

function renderItem(item){
    item.metricsArr = []
    for (metricName in item.metrics){
        thisMetric = item.metrics[metricName]
        thisMetric.name = metricName
        var latestTs = getLatestTs(item.metrics[metricName].values)
        if (latestTs) {
            var latestVal = item.metrics[metricName].values[latestTs]
            thisMetric.ts = latestTs
            thisMetric.value = latestVal
        }

        // if no values, no point in printing
        if (thisMetric.value) {
            item.metricsArr.push(thisMetric)
        }
    }

    item.metricsArr.sort(sortByMetricValueDesc)

    var url = (item.aliases.url) ?  item.aliases.url[0] : false
    var html$ = ich.item(item)
    var biblioHtml = renderItemBiblio(item.biblio, url)
    html$.find("div.biblio").append(biblioHtml)

    return html$
}

function getNewItemsAndUpdateReport() {
    tiidsStr = tiids.join(",")

    $.ajax({
        url: "http://"+api_root+'/items/'+tiidsStr,
        type: "GET",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function(data){
            $("ul#items").empty()
            for (i in data){
                // make the set of all newly-rendered items
                // this is a very slow way to do this...should bundle together,
                // then make one replace.
                var genre = data[i].biblio.genre
                var genreItems = "div." + genre + " ul#items"
                $(genreItems).append(renderItem(data[i]))
                $("div." + genre).show()  // would ideally only do this once
            }
        }
    });
}

function pollApiAndUpdateCollection(interval, oldText, tries){
    getNewItemsAndUpdateReport();
    // has anything changed?
    currentText = $("#metrics").text()
    if (currentText == oldText) {
        console.log("current and old text match; on try "+tries)
        tries++;
        if (tries > 10) {
            console.log("done with updating")
            $("#page-header img").remove()
            $(""+tiids.length+" items")
                .hide()
                .insertAfter("#report-button")
                .show();
            return false
        }
    }
    else {
        tries = 0
    }

    setTimeout(function(){
        pollApiAndUpdateCollection(interval, currentText, tries);
    }, interval)
}

$(document).ready(function(){

    // report page stuff
    $('ul.metrics li').tooltip();

    // dialog for supported IDs
    $("div#paste-ids legend a").click(function(){
        // get the contents
        TINY.box.show({url:'../static/whichartifacts.html'})
        return false;
    });

    // table of contents
    if ($("#toc")[0]) {
        $('#toc').tocBuilder({type: 'headings', startLevel: 3, endLevel: 3, insertBackLinks: 0});

    }

    createCollectionInit();

    // updating the collection from the report page
    $("#update-report-button").click(function(){
        $("h2 img").show()
        $.ajax({
            url: "http://"+api_root+'/items',
            type: "POST",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(tiids),
            success: function(data){
                //window.location.reload(false);
                console.log("updating.")
                pollApiAndUpdateCollection(500, "", 0);
            }});
        return false;
    })

    if (typeof tiids != "undefined"){
        $("h2").before(ajaxLoadImgRev)
        pollApiAndUpdateCollection(500, "", 0);
    }

});
<commit_msg>return joined id to fix github bug<commit_after>$.ajaxSetup ({
    cache: false
});
var ajaxLoadImg = "";
var ajaxLoadImgRev = "";
var collectionIds = []
var currentUserInputValue = ""

/*****************************************************************************
 * create collection page
 ****************************************************************************/

exampleStrings = {
    paste_input:"doi:10.123/somejournal/123\nhttp://www.example.com",
    crossref_input: "Watson:  A Structure for Deoxyribose Nucleic Acid\nGeertz: Deep play: Notes on the Balinese cockfight",
    name: "My Collection"
}

inputExamplesIClickHandler = function(thisInput) {

}

flatten = function(idsArr) {
    // flattens id values that are themselves arrays (like github)
    var aliases = [];
    numIds = idsArr.length;
    for (var i=0; i<numIds; i++ ) {
        var id = idsArr[i][1]
        var namespace = idsArr[i][0]
        if( Object.prototype.toString.call( id ) === '[object Array]' ) {
            var strVal = id.join(",")
        }
        else {
            var strVal = id
        }
        aliases.push([namespace, strVal])
    }
    return(aliases)
}

addCollectionIds = function(idsArr, $this) {
    var startingCollectionLength = collectionIds.length
    var newIds = flatten(idsArr);

    // make an object with the unique key values
    var uniqueNamespaceIdPairs = {}
    for  (var i=0; i<collectionIds.length; i++){
        var namespaceIdPair = collectionIds[i].join(":")
        uniqueNamespaceIdPairs[namespaceIdPair] = 1
    }
    console.log(uniqueNamespaceIdPairs)

    for (var i=0; i < newIds.length; i++){
        var newNamespaceIdPair = newIds[i].join(":")
        if (!uniqueNamespaceIdPairs[newNamespaceIdPair]) {
            collectionIds.push(newIds[i])
        }
    }
    $("span.loading").remove()

    // how many items are in the new collection now?
    var endingCollectionLength = collectionIds.length;
    numIdsAdded = endingCollectionLength - startingCollectionLength;
    $("#artcounter span.count").html(endingCollectionLength);
    if (numIdsAdded) {
        $this.siblings("span.added").remove()
        $this.after(""+numIdsAdded+" items added.")
        $this.siblings("span.added")
            .find("span.count")
                .css({color: "#ff4e00"})
                .animate({color: "#555555"}, 1000)

    }
    return true;

}

// puts the textarea-entered ids in a format that addcollectionIds likes
parseTextareaArtifacts = function(str) {
    var ids = str.split("\n");
    var ret = [];
    for (i=0; i<ids.length; i++){
        var artifact = [];
        var thisId = ids[i];
        if (thisId.indexOf(":") > 0) {
            artifact[0] = thisId.split(':')[0]; // namespace
            artifact[1] = thisId.substr(artifact[0].length + 1) // id

            // handle urls:
            if (artifact[0] == "http"){
                artifact[0] = "url";
                artifact[1] = thisId
            }
        }
        else {
            if (thisId.length > 0) {
                // handle dois entered without the doi prefix
                if (thisId.substring(0,3) == "10.") {
                    artifact[0] = "doi"
                } else {
                   artifact[0] = "unknown"
                }
                artifact[1] = thisId
            }
        }
        if (typeof artifact[1] != "undefined") {
            ret.push(artifact);
        }
    }
    return ret;
}
userInputHandler = function($this, prevValue) {
    $this.blur(function(){

    });

}

upload_bibtex = function(files) {
    var fileInput = $("li #input_bibtex")[0];
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('file', file);
    $("li #input_bibtex").siblings("span.added").remove()
    $("li #input_bibtex").after(""+ajaxLoadImg+"");

    $.ajax({
            url: "http://"+api_root+'/provider/bibtex/memberitems',
            type: "POST",
            processData: false,
            contentType: false,
            data: formData,
            success:  function(response,status,xhr){
                addCollectionIds(response, $("li #input_bibtex"))
        }});
    }

createCollectionInit = function(){

    $("li textarea, input#name").each(function(){
        $(this).val(exampleStrings[this.id])
    })
    $("li input, li textarea, input#name")
    .focus(function(){
        currentUserInputValue = $(this).val();
        $(this).removeClass("no-input-yet")

        // hid the example strings if they're still up.
        if (currentUserInputValue == exampleStrings[this.id]) {
            $(this).val("")
        }
    })
    .blur(function(){
        $this = $(this)
        if ($this.val() == "") {
            $this.addClass("no-input-yet")
            $this.val(exampleStrings[this.id])
            return false;
        }
        else if ($this.val() == currentUserInputValue) {
            return false;
        }

        if ($this.attr("id") == "paste_input") {
            newIds = parseTextareaArtifacts($(this).val());
            addCollectionIds(newIds, $(this))
        }
        else {
            var idStrParts = $(this).attr("id").split('_');
            var providerName = idStrParts[0];

            if (providerName == "crossref") { // hack, should generalize for all textareas
                var providerTypeQuery = "&type=import"
                var pipeVal = $this.val().replace(":", "|");
                var providerIdQuery = "?query=" + escape(pipeVal);
            } else {
                var providerTypeQuery = "&type=" + $this.attr("name");
                var providerIdQuery = "?query=" + escape($this.val());
            }
            $(this).siblings("span.added").remove()
            $(this).after(""+ajaxLoadImg+"");
            $.get("http://"+api_root+"/provider/"+providerName+"/memberitems"+providerIdQuery+providerTypeQuery, function(response,status,xhr){
                addCollectionIds(response, $this)
            }, "json");

        }
    })

    // creating a collection by submitting the object IDs from the homepage
    $("#id-form").submit(function(){

        // make sure the user input something at all
        if (collectionIds.length == 0) {
            alert("Looks like you haven't added any research objects to the collection yet.")
            return false;

        // created items and put them in a collection, then redirect to
        // the collection report page:
        } else {
            // first we upload the new items and get tiids back.
            console.log("adding new items.")
            $("#go-button").replaceWith(""+ajaxLoadImg+"")
            $.ajax({
                url: "http://"+api_root+'/items',
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify(collectionIds),
                success: function(returnedTiids){
                    // make a new collection, populated by our freshly-minted tiids
                    console.log("items created. making collection.")
                    var requestObj = {
                        title: $('#name').val(),
                        items: returnedTiids
                    }

                    $.ajax({
                        url: "http://"+api_root+'/collection',
                        type: "POST",
                        dataType: "json",
                        contentType: "application/json; charset=utf-8",
                        data:  JSON.stringify(requestObj),
                        success: function(returnedCollection){

                            // we've created the items and the collection; our
                            // work here is done.
                            console.log(returnedCollection)
                            location.href = "/collection/" +returnedCollection.id;
                        }
                    });
                }
            });
            return false;
        }
    });
}

/*****************************************************************************
 * report page
 ****************************************************************************/

function renderItemBiblio(biblio, url) {
    var html = ""

    biblio.url = url
    biblio.title = biblio.title || "no title"
    if (biblio.create_date) {
        biblio.year = biblio.create_date.slice(0,4)
    }

    var templateName = "biblio_" + biblio.genre
    return ich[templateName](biblio, true)
}

getLatestTs = function(metricSnaps) {
    var latestTs = "1999-01-01T00:00:00.000000"
    for (ts in metricSnaps) {
        if (ts > latestTs) {
            latestTs = ts
        }
    }
    return latestTs
}

function sortByMetricValueDesc(metric1, metric2){
  if (metric1.value < metric2.value)
     return 1;
  if (metric1.value > metric2.value)
    return -1;
  return 0;
}

function renderItem(item){
    item.metricsArr = []
    for (metricName in item.metrics){
        thisMetric = item.metrics[metricName]
        thisMetric.name = metricName
        var latestTs = getLatestTs(item.metrics[metricName].values)
        if (latestTs) {
            var latestVal = item.metrics[metricName].values[latestTs]
            thisMetric.ts = latestTs
            thisMetric.value = latestVal
        }

        // if no values, no point in printing
        if (thisMetric.value) {
            item.metricsArr.push(thisMetric)
        }
    }

    item.metricsArr.sort(sortByMetricValueDesc)

    var url = (item.aliases.url) ?  item.aliases.url[0] : false
    var html$ = ich.item(item)
    var biblioHtml = renderItemBiblio(item.biblio, url)
    html$.find("div.biblio").append(biblioHtml)

    return html$
}

function getNewItemsAndUpdateReport() {
    tiidsStr = tiids.join(",")

    $.ajax({
        url: "http://"+api_root+'/items/'+tiidsStr,
        type: "GET",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function(data){
            $("ul#items").empty()
            for (i in data){
                // make the set of all newly-rendered items
                // this is a very slow way to do this...should bundle together,
                // then make one replace.
                var genre = data[i].biblio.genre
                var genreItems = "div." + genre + " ul#items"
                $(genreItems).append(renderItem(data[i]))
                $("div." + genre).show()  // would ideally only do this once
            }
        }
    });
}

function pollApiAndUpdateCollection(interval, oldText, tries){
    getNewItemsAndUpdateReport();
    // has anything changed?
    currentText = $("#metrics").text()
    if (currentText == oldText) {
        console.log("current and old text match; on try "+tries)
        tries++;
        if (tries > 10) {
            console.log("done with updating")
            $("#page-header img").remove()
            $(""+tiids.length+" items")
                .hide()
                .insertAfter("#report-button")
                .show();
            return false
        }
    }
    else {
        tries = 0
    }

    setTimeout(function(){
        pollApiAndUpdateCollection(interval, currentText, tries);
    }, interval)
}

$(document).ready(function(){

    // report page stuff
    $('ul.metrics li').tooltip();

    // dialog for supported IDs
    $("div#paste-ids legend a").click(function(){
        // get the contents
        TINY.box.show({url:'../static/whichartifacts.html'})
        return false;
    });

    // table of contents
    if ($("#toc")[0]) {
        $('#toc').tocBuilder({type: 'headings', startLevel: 3, endLevel: 3, insertBackLinks: 0});

    }

    createCollectionInit();

    // updating the collection from the report page
    $("#update-report-button").click(function(){
        $("h2 img").show()
        $.ajax({
            url: "http://"+api_root+'/items',
            type: "POST",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(tiids),
            success: function(data){
                //window.location.reload(false);
                console.log("updating.")
                pollApiAndUpdateCollection(500, "", 0);
            }});
        return false;
    })

    if (typeof tiids != "undefined"){
        $("h2").before(ajaxLoadImgRev)
        pollApiAndUpdateCollection(500, "", 0);
    }

});
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

//
FBL.ns(function() { with (FBL) {

// ************************************************************************************************
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

top.Firebug.Console.injector =
{
    isAttached: function(context, win)
    {
        if (win.wrappedJSObject)
        {
            var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject));

            return attached;
        }
        else
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement);
            return (win._getFirebugConsoleElement ? true : false);
        }
    },

    attachIfNeeded: function(context, win)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") );

        if (this.isAttached(context, win))
            return true;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded found isAttached false ");

        this.attachConsoleInjector(context, win);
        this.addConsoleListener(context, win);

        Firebug.Console.clear(context); // remove the warning about reloading.

        var attached =  this.isAttached(context, win);
        if (attached)
            dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]);

        return attached;
    },

    attachConsoleInjector: function(context, win)
    {
        var consoleInjection = this.getConsoleInjectionScript();  // Do it all here.

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection);

        Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location);
    },

    getConsoleInjectionScript: function() {
        if (!this.consoleInjectionScript)
        {
            var script = "";
            script += "window.__defineGetter__('console', function() {\n";
            script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n";

            script += "window.loadFirebugConsole = function() {\n";
            script += "window._firebug =  new _FirebugConsole();";

            if (FBTrace.DBG_CONSOLE)
                script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n";

            script += " return window._firebug };\n";

            var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");
            script += theFirebugConsoleScript;

            this.consoleInjectionScript = script;
        }
        return this.consoleInjectionScript;
    },

    forceConsoleCompilationInPage: function(context, win)
    {
        if (!win)
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("no win in forceConsoleCompilationInPage!");
            return;
        }

        var consoleForcer = "window.loadFirebugConsole();";

        if (context.stopped)
            Firebug.Console.injector.evaluateConsoleScript(context);  // todo evaluate consoleForcer on stack
        else
            Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer);
    },

    evaluateConsoleScript: function(context)
    {
        var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript
        Firebug.Debugger.evaluate(scriptSource, context);
    },

    addConsoleListener: function(context, win)
    {
        if (!context.activeConsoleHandlers)  // then we have not been this way before
            context.activeConsoleHandlers = [];
        else
        {   // we've been this way before...
            for (var i=0; i<context.activeConsoleHandlers.length; i++)
            {
                if (context.activeConsoleHandlers[i].window == win)
                {
                    context.activeConsoleHandlers[i].detach();
                    if (FBTrace.DBG_CONSOLE)
                        FBTrace.sysout("consoleInjector addConsoleListener removed handler("+context.activeConsoleHandlers[i].handler_name+") from _firebugConsole in : "+win.location+"\n");
                    context.activeConsoleHandlers.splice(i,1);
                }
            }
        }

        // We need the element to attach our event listener.
        var element = Firebug.Console.getFirebugConsoleElement(context, win);
        element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version.

        var handler = new FirebugConsoleHandler(context, win);
        handler.attachTo(element);

        context.activeConsoleHandlers.push(handler);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n");
        return true;
    },

    detachConsole: function(context, win)
    {
        var element = win.document.getElementById("_firebugConsole");
        if (element)
            element.parentNode.removeChild(element);
    },
}

var total_handlers = 0;
function FirebugConsoleHandler(context, win)
{
    this.window = win;

    this.attachTo = function(element)
    {
        this.element = element;
        // When raised on our injected element, callback to Firebug and append to console
        this.boundHandler = bind(this.handleEvent, this);
        this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing
    };

    this.detach = function()
    {
        this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true);
    };

    this.handler_name = ++total_handlers;
    this.handleEvent = function(event)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event);
        if (!Firebug.CommandLine.CommandHandler.handle(event, this, win))
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("FirebugConsoleHandler", this);

            var methodName = event.target.getAttribute("methodName");
            Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
        }
    };

    this.firebug = Firebug.version;

    this.init = function()
    {
        var consoleElement = win.document.getElementById('_firebugConsole');
        consoleElement.setAttribute("FirebugVersion", Firebug.version);
    };

    this.log = function()
    {
        logFormatted(arguments, "log");
    };

    this.debug = function()
    {
        logFormatted(arguments, "debug", true);
    };

    this.info = function()
    {
        logFormatted(arguments, "info", true);
    };

    this.warn = function()
    {
        logFormatted(arguments, "warn", true);
    };

    this.error = function()
    {
        Firebug.Errors.increaseCount(context);
        logAssert("error", arguments);
    };

    this.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            logAssert("assert", rest);
        }
    };

    this.dir = function(o)
    {
        Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
    };

    this.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
    };

    this.trace = function()
    {
        var trace = getJSDUserStack();
        Firebug.Console.log(trace, context, "stackTrace");
    };

    this.group = function()
    {
        var sourceLink = getStackLink();
        Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
    };

    this.groupEnd = function()
    {
        Firebug.Console.closeGroup(context);
    };

    this.groupCollapsed = function()
    {
        var sourceLink = getStackLink();
        // noThrottle true is probably ok, openGroups will likely be short strings.
        var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
        removeClass(row, "opened");
    };

    this.profile = function(title)
    {
        Firebug.Profiler.startProfiling(context, title);
    };

    this.profileEnd = function()
    {
        Firebug.Profiler.stopProfiling(context);
    };

    this.count = function(key)
    {
        var frameId = FBL.getStackFrameId();
        if (frameId)
        {
            if (!context.frameCounters)
                context.frameCounters = {};

            if (key != undefined)
                frameId += key;

            var frameCounter = context.frameCounters[frameId];
            if (!frameCounter)
            {
                var logRow = logFormatted(["0"], null, true, true);

                frameCounter = {logRow: logRow, count: 1};
                context.frameCounters[frameId] = frameCounter;
            }
            else
                ++frameCounter.count;

            var label = key == undefined
                ? frameCounter.count
                : key + " " + frameCounter.count;

            frameCounter.logRow.firstChild.firstChild.nodeValue = label;
        }
    };

    this.clear = function()
    {
        Firebug.Console.clear(context);
    };

    this.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        var key = "KEY"+name.toString();

        if (!reset && this.timeCounters[key])
            return;

        this.timeCounters[key] = time;
    };

    this.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var key = "KEY"+name.toString();

        var timeCounter = this.timeCounters[key];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.info(label);

            delete this.timeCounters[key];
        }
        return diff;
    };

    // These functions are over-ridden by commandLine
    this.evaluated = function(result, context)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result);

        Firebug.Console.log(result, context);
    };
    this.evaluateError = function(result, context)
    {
        Firebug.Console.log(result, context, "errorMessage");
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    function logFormatted(args, className, linkToSource, noThrottle)
    {
        var sourceLink = linkToSource ? getStackLink() : null;
        return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
    }

    function logAssert(category, args)
    {
        Firebug.Errors.increaseCount(context);

        if (!args || !args.length || args.length == 0)
            var msg = [FBL.$STR("Assertion")];
        else
            var msg = args[0];

        var sourceName = win.location;
        var lineNumber = 0;
        if (msg.stack)
            var trace = parseToStackTrace(msg.stack);
        else
        {
            var trace = getJSDUserStack();
            if (trace && trace.frames && trace.frames[0])
            {
                var frame = trace.frames[0];
                sourceName = normalizeURL(frame.script.fileName);
                lineNumber = frame.line;
                if (lineNumber && sourceName)
                    var sourceLine = context.sourceCache.getLine(sourceName, lineNumber);
            }
        }
        if (msg.fileName)
            sourceName = msg.fileName;
        if (msg.lineNumber)
            lineNumber = msg.lineNumber;

        var errorObject = new FBL.ErrorMessage(msg, sourceName,
                        lineNumber, (sourceLine?sourceLine:""), category, context, trace);

        var row = Firebug.Console.log(errorObject, context, "errorMessage", null, true); // noThrottle
        row.scrollIntoView();
    }

    function getComponentsStackDump()
    {
        // Starting with our stack, walk back to the user-level code
        var frame = Components.stack;
        var userURL = win.location.href.toString();

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame);

        // Drop frames until we get into user code.
        while (frame && FBL.isSystemURL(frame.filename) )
            frame = frame.caller;

        // Drop two more frames, the injected console function and firebugAppendConsole()
        if (frame)
            frame = frame.caller;
        if (frame)
            frame = frame.caller;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame);

        return frame;
    }

    function getStackLink()
    {
        return FBL.getFrameSourceLink(getComponentsStackDump());
    }

    function getJSDUserStack()
    {
        var trace = FBL.getCurrentStackTrace(context);

        var frames = trace ? trace.frames : null;
        if (frames && (frames.length > 0) )
        {
            var oldest = frames.length - 1;  // 6 - 1 = 5
            for (var i = 0; i < frames.length; i++)
            {
                if (frames[oldest - i].href.indexOf("chrome:") == 0) break;
                var fn = frames[oldest - i].fn + "";
                if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break;  // command line
            }
            FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace);
            trace.frames = trace.frames.slice(2 - i);  // take the oldest frames, leave 2 behind they are injection code

            return trace;
        }
        else
            return "Firebug failed to get stack trace with any frames";
    }
}

}});
<commit_msg>avoid NPE, but its when the console is going to fail.<commit_after>/* See license.txt for terms of usage */

//
FBL.ns(function() { with (FBL) {

// ************************************************************************************************
// Constants

const Cc = Components.classes;
const Ci = Components.interfaces;

top.Firebug.Console.injector =
{
    isAttached: function(context, win)
    {
        if (win.wrappedJSObject)
        {
            var attached = (win.wrappedJSObject._getFirebugConsoleElement ? true : false);
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached:"+attached+" to win.wrappedJSObject "+safeGetWindowLocation(win.wrappedJSObject));

            return attached;
        }
        else
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("Console.isAttached? to win "+win.location+" fnc:"+win._getFirebugConsoleElement);
            return (win._getFirebugConsoleElement ? true : false);
        }
    },

    attachIfNeeded: function(context, win)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded has win "+(win? ((win.wrappedJSObject?"YES":"NO")+" wrappedJSObject"):"null") );

        if (this.isAttached(context, win))
            return true;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("Console.attachIfNeeded found isAttached false ");

        this.attachConsoleInjector(context, win);
        this.addConsoleListener(context, win);

        Firebug.Console.clear(context); // remove the warning about reloading.

        var attached =  this.isAttached(context, win);
        if (attached)
            dispatch(Firebug.Console.fbListeners, "onConsoleInjected", [context, win]);

        return attached;
    },

    attachConsoleInjector: function(context, win)
    {
        var consoleInjection = this.getConsoleInjectionScript();  // Do it all here.

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluating in "+win.location, consoleInjection);

        Firebug.CommandLine.evaluateInWebPage(consoleInjection, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("attachConsoleInjector evaluation completed for "+win.location);
    },

    getConsoleInjectionScript: function() {
        if (!this.consoleInjectionScript)
        {
            var script = "";
            script += "window.__defineGetter__('console', function() {\n";
            script += " return (window._firebug ? window._firebug : window.loadFirebugConsole()); })\n\n";

            script += "window.loadFirebugConsole = function() {\n";
            script += "window._firebug =  new _FirebugConsole();";

            if (FBTrace.DBG_CONSOLE)
                script += " window.dump('loadFirebugConsole '+window.location+'\\n');\n";

            script += " return window._firebug };\n";

            var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");
            script += theFirebugConsoleScript;

            this.consoleInjectionScript = script;
        }
        return this.consoleInjectionScript;
    },

    forceConsoleCompilationInPage: function(context, win)
    {
        if (!win)
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("no win in forceConsoleCompilationInPage!");
            return;
        }

        var consoleForcer = "window.loadFirebugConsole();";

        if (context.stopped)
            Firebug.Console.injector.evaluateConsoleScript(context);  // todo evaluate consoleForcer on stack
        else
            Firebug.CommandLine.evaluateInWebPage(consoleForcer, context, win);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("forceConsoleCompilationInPage "+win.location, consoleForcer);
    },

    evaluateConsoleScript: function(context)
    {
        var scriptSource = this.getConsoleInjectionScript(); // TODO XXXjjb this should be getConsoleInjectionScript
        Firebug.Debugger.evaluate(scriptSource, context);
    },

    addConsoleListener: function(context, win)
    {
        if (!context.activeConsoleHandlers)  // then we have not been this way before
            context.activeConsoleHandlers = [];
        else
        {   // we've been this way before...
            for (var i=0; i<context.activeConsoleHandlers.length; i++)
            {
                if (context.activeConsoleHandlers[i].window == win)
                {
                    context.activeConsoleHandlers[i].detach();
                    if (FBTrace.DBG_CONSOLE)
                        FBTrace.sysout("consoleInjector addConsoleListener removed handler("+context.activeConsoleHandlers[i].handler_name+") from _firebugConsole in : "+win.location+"\n");
                    context.activeConsoleHandlers.splice(i,1);
                }
            }
        }

        // We need the element to attach our event listener.
        var element = Firebug.Console.getFirebugConsoleElement(context, win);
        if (element)
            element.setAttribute("FirebugVersion", Firebug.version); // Initialize Firebug version.
        else
            return false;

        var handler = new FirebugConsoleHandler(context, win);
        handler.attachTo(element);

        context.activeConsoleHandlers.push(handler);

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector addConsoleListener attached handler("+handler.handler_name+") to _firebugConsole in : "+win.location+"\n");
        return true;
    },

    detachConsole: function(context, win)
    {
        var element = win.document.getElementById("_firebugConsole");
        if (element)
            element.parentNode.removeChild(element);
    },
}

var total_handlers = 0;
function FirebugConsoleHandler(context, win)
{
    this.window = win;

    this.attachTo = function(element)
    {
        this.element = element;
        // When raised on our injected element, callback to Firebug and append to console
        this.boundHandler = bind(this.handleEvent, this);
        this.element.addEventListener('firebugAppendConsole', this.boundHandler, true); // capturing
    };

    this.detach = function()
    {
        this.element.removeEventListener('firebugAppendConsole', this.boundHandler, true);
    };

    this.handler_name = ++total_handlers;
    this.handleEvent = function(event)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("FirebugConsoleHandler("+this.handler_name+") "+event.target.getAttribute("methodName")+", event", event);
        if (!Firebug.CommandLine.CommandHandler.handle(event, this, win))
        {
            if (FBTrace.DBG_CONSOLE)
                FBTrace.sysout("FirebugConsoleHandler", this);

            var methodName = event.target.getAttribute("methodName");
            Firebug.Console.log($STRF("console.MethodNotSupported", [methodName]));
        }
    };

    this.firebug = Firebug.version;

    this.init = function()
    {
        var consoleElement = win.document.getElementById('_firebugConsole');
        consoleElement.setAttribute("FirebugVersion", Firebug.version);
    };

    this.log = function()
    {
        logFormatted(arguments, "log");
    };

    this.debug = function()
    {
        logFormatted(arguments, "debug", true);
    };

    this.info = function()
    {
        logFormatted(arguments, "info", true);
    };

    this.warn = function()
    {
        logFormatted(arguments, "warn", true);
    };

    this.error = function()
    {
        Firebug.Errors.increaseCount(context);
        logAssert("error", arguments);
    };

    this.assert = function(x)
    {
        if (!x)
        {
            var rest = [];
            for (var i = 1; i < arguments.length; i++)
                rest.push(arguments[i]);
            logAssert("assert", rest);
        }
    };

    this.dir = function(o)
    {
        Firebug.Console.log(o, context, "dir", Firebug.DOMPanel.DirTable);
    };

    this.dirxml = function(o)
    {
        if (o instanceof Window)
            o = o.document.documentElement;
        else if (o instanceof Document)
            o = o.documentElement;

        Firebug.Console.log(o, context, "dirxml", Firebug.HTMLPanel.SoloElement);
    };

    this.trace = function()
    {
        var trace = getJSDUserStack();
        Firebug.Console.log(trace, context, "stackTrace");
    };

    this.group = function()
    {
        var sourceLink = getStackLink();
        Firebug.Console.openGroup(arguments, null, "group", null, false, sourceLink);
    };

    this.groupEnd = function()
    {
        Firebug.Console.closeGroup(context);
    };

    this.groupCollapsed = function()
    {
        var sourceLink = getStackLink();
        // noThrottle true is probably ok, openGroups will likely be short strings.
        var row = Firebug.Console.openGroup(arguments, null, "group", null, true, sourceLink);
        removeClass(row, "opened");
    };

    this.profile = function(title)
    {
        Firebug.Profiler.startProfiling(context, title);
    };

    this.profileEnd = function()
    {
        Firebug.Profiler.stopProfiling(context);
    };

    this.count = function(key)
    {
        var frameId = FBL.getStackFrameId();
        if (frameId)
        {
            if (!context.frameCounters)
                context.frameCounters = {};

            if (key != undefined)
                frameId += key;

            var frameCounter = context.frameCounters[frameId];
            if (!frameCounter)
            {
                var logRow = logFormatted(["0"], null, true, true);

                frameCounter = {logRow: logRow, count: 1};
                context.frameCounters[frameId] = frameCounter;
            }
            else
                ++frameCounter.count;

            var label = key == undefined
                ? frameCounter.count
                : key + " " + frameCounter.count;

            frameCounter.logRow.firstChild.firstChild.nodeValue = label;
        }
    };

    this.clear = function()
    {
        Firebug.Console.clear(context);
    };

    this.time = function(name, reset)
    {
        if (!name)
            return;

        var time = new Date().getTime();

        if (!this.timeCounters)
            this.timeCounters = {};

        var key = "KEY"+name.toString();

        if (!reset && this.timeCounters[key])
            return;

        this.timeCounters[key] = time;
    };

    this.timeEnd = function(name)
    {
        var time = new Date().getTime();

        if (!this.timeCounters)
            return;

        var key = "KEY"+name.toString();

        var timeCounter = this.timeCounters[key];
        if (timeCounter)
        {
            var diff = time - timeCounter;
            var label = name + ": " + diff + "ms";

            this.info(label);

            delete this.timeCounters[key];
        }
        return diff;
    };

    // These functions are over-ridden by commandLine
    this.evaluated = function(result, context)
    {
        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.FirebugConsoleHandler evalutated default called", result);

        Firebug.Console.log(result, context);
    };
    this.evaluateError = function(result, context)
    {
        Firebug.Console.log(result, context, "errorMessage");
    };

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    function logFormatted(args, className, linkToSource, noThrottle)
    {
        var sourceLink = linkToSource ? getStackLink() : null;
        return Firebug.Console.logFormatted(args, context, className, noThrottle, sourceLink);
    }

    function logAssert(category, args)
    {
        Firebug.Errors.increaseCount(context);

        if (!args || !args.length || args.length == 0)
            var msg = [FBL.$STR("Assertion")];
        else
            var msg = args[0];

        var sourceName = win.location;
        var lineNumber = 0;
        if (msg.stack)
            var trace = parseToStackTrace(msg.stack);
        else
        {
            var trace = getJSDUserStack();
            if (trace && trace.frames && trace.frames[0])
            {
                var frame = trace.frames[0];
                sourceName = normalizeURL(frame.script.fileName);
                lineNumber = frame.line;
                if (lineNumber && sourceName)
                    var sourceLine = context.sourceCache.getLine(sourceName, lineNumber);
            }
        }
        if (msg.fileName)
            sourceName = msg.fileName;
        if (msg.lineNumber)
            lineNumber = msg.lineNumber;

        var errorObject = new FBL.ErrorMessage(msg, sourceName,
                        lineNumber, (sourceLine?sourceLine:""), category, context, trace);

        var row = Firebug.Console.log(errorObject, context, "errorMessage", null, true); // noThrottle
        row.scrollIntoView();
    }

    function getComponentsStackDump()
    {
        // Starting with our stack, walk back to the user-level code
        var frame = Components.stack;
        var userURL = win.location.href.toString();

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump initial stack for userURL "+userURL, frame);

        // Drop frames until we get into user code.
        while (frame && FBL.isSystemURL(frame.filename) )
            frame = frame.caller;

        // Drop two more frames, the injected console function and firebugAppendConsole()
        if (frame)
            frame = frame.caller;
        if (frame)
            frame = frame.caller;

        if (FBTrace.DBG_CONSOLE)
            FBTrace.sysout("consoleInjector.getComponentsStackDump final stack for userURL "+userURL, frame);

        return frame;
    }

    function getStackLink()
    {
        return FBL.getFrameSourceLink(getComponentsStackDump());
    }

    function getJSDUserStack()
    {
        var trace = FBL.getCurrentStackTrace(context);

        var frames = trace ? trace.frames : null;
        if (frames && (frames.length > 0) )
        {
            var oldest = frames.length - 1;  // 6 - 1 = 5
            for (var i = 0; i < frames.length; i++)
            {
                if (frames[oldest - i].href.indexOf("chrome:") == 0) break;
                var fn = frames[oldest - i].fn + "";
                if (fn && (fn.indexOf("_firebugEvalEvent") != -1) ) break;  // command line
            }
            FBTrace.sysout("consoleInjector getJSDUserStack: "+frames.length+" oldest: "+oldest+" i: "+i+" i - oldest + 2: "+(i - oldest + 2), trace);
            trace.frames = trace.frames.slice(2 - i);  // take the oldest frames, leave 2 behind they are injection code

            return trace;
        }
        else
            return "Firebug failed to get stack trace with any frames";
    }
}

}});
<|endoftext|>


<commit_before>import React from 'react'
import echarts from 'echarts'
import _ from 'lodash'
import fetch from 'isomorphic-fetch'
import moment from 'moment'

import styles from './Main.css'
import Loading from '../Loading'

import { autobind } from 'react-decoration'
import { Checkbox } from 'antd'
import { checkStatus, serverAddress } from '../../util'

const refName = 'AbsoluteTrend'

const rawDateFormat = 'YYYY-MM-DD'
const dateFormat = 'YYYY-MM'

const CheckboxGroup = Checkbox.Group

const getMaCalculator = (values) => (dayCount) => {
  const result = []
  for (let i = 0, len = values.length; i < len; i++) {
    if (i < dayCount) {
      result.push('-')
      continue
    }
    let sum = 0
    for (let j = 0; j < dayCount; j++) {
      sum += values[i - j]
    }
    result.push(sum / dayCount)
  }
  return result
}

const getOption = (trend) => {
  const calculateMA = getMaCalculator(trend.values)
  const legend = ['月线', 'MA3', 'MA5']
  return {
    title: {
      text: '绝对趋势',
      left: 100
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: legend
    },
    grid: {
      left: '10%',
      right: '10%',
      bottom: '15%'
    },
    xAxis: {
      type: 'category',
      data: trend.categoryData,
      scale: true,
      boundaryGap: false,
      axisLine: {onZero: false},
      splitLine: {show: false},
      splitNumber: 20,
      min: 'dataMin',
      max: 'dataMax'
    },
    yAxis: {
      scale: true,
      splitArea: {
        show: true
      }
    },
    dataZoom: [
      {
        type: 'inside',
        start: 50,
        end: 100
      },
      {
        show: true,
        type: 'slider',
        y: '90%',
        start: 50,
        end: 100
      }
    ],
    series: [
      {
        name: '月线',
        type: 'line',
        data: calculateMA(1),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      },
      {
        name: 'MA3',
        type: 'line',
        data: calculateMA(3),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      },
      {
        name: 'MA5',
        type: 'line',
        data: calculateMA(5),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      }
    ]
  }
}

const topicName = (index) => (`主题${index + 1}`)

const transformData = (rawData) => {
  const totalTrend = {}
  const topicTrend = []

  rawData.forEach(data => {
    const date = moment(data.date, rawDateFormat).format(dateFormat)
    totalTrend[date] = _.get(totalTrend, date, 0) + 1
    const lda = data.lda
    const topic = lda.indexOf(Math.max(...lda))
    if (_.isEmpty(topicTrend[topic])) {
      topicTrend[topic] = {}
      topicTrend[topic][date] = 1
    } else {
      topicTrend[topic][date] = _.get(topicTrend[topic], date, 0) + 1
    }
  })

  const categoryData = []
  const topicsName = topicTrend.map((topic, index) => (topicName(index)))
  const topicValues = {}
  topicsName.forEach(topicName => { topicValues[topicName] = [] })

  _.forIn(totalTrend, (totalAmount, date) => {
    categoryData.push(date)
    topicTrend.forEach((topic, index) => {
      topicValues[topicName(index)].push(_.get(topic, date, 0) / totalAmount)
    })
  })
  console.log(topicValues)
  return {categoryData, topicValues, topicsName}
}

export default class AbsoluteTrend extends React.Component {
  constructor () {
    super()
    this.state = {
      categoryData: [],
      topicValues: [],
      checkedList: [],
      topics: [],
      indeterminate: true,
      checkAll: false
    }
    fetch(`${serverAddress}/lda-doc`, { method: 'GET' })
      .then(checkStatus)
      .then((res) => (res.json()))
      .then((doc) => {
        const data = transformData(doc)
        this.setState({
          ...this.state,
          categoryData: data.categoryData,
          topicValues: data.topicValues,
          checkedList: [data.topic[0]],
          topics: data.topics
        })
      }) // todo draw
  }

  isDataLoaded () {
    return !_.isEmpty(this.state.topics)
  }

  componentDidMount () {
    this.myChart = echarts.init(this.refs[refName])
  }

  @autobind
  onChange (checkedList) {
    const plainOptions = this.state.topics
    this.setState({
      ...this.state,
      checkedList,
      indeterminate: !!checkedList.length && (checkedList.length < plainOptions.length),
      checkAll: checkedList.length === plainOptions.length
    })
  }

  @autobind
  onCheckAllChange (e) {
    this.setState({
      ...this.state,
      checkedList: e.target.checked ? this.state.topics : [],
      indeterminate: false,
      checkAll: e.target.checked
    })
  }

  @autobind
  drawAbsoluteTrend () {
    const option = getOption(this.state.trend)
    this.myChart.setOption(option)
  }

  @autobind
  drawCheckbox () {
    return

        <Checkbox
          indeterminate={this.state.indeterminate}
          onChange={this.onCheckAllChange}
          checked={this.state.checkAll}
        >
          全选
        </Checkbox>

      <CheckboxGroup options={this.state.topics} value={this.state.checkedList} onChange={this.onChange} />

  }

  render () {
    return

      {this.isDataLoaded()
        ? this.drawCheckbox()
        : <Loading />}

  }
}
<commit_msg>rename<commit_after>import React from 'react'
import echarts from 'echarts'
import _ from 'lodash'
import fetch from 'isomorphic-fetch'
import moment from 'moment'

import styles from './Main.css'
import Loading from '../Loading'

import { autobind } from 'react-decoration'
import { Checkbox } from 'antd'
import { checkStatus, serverAddress } from '../../util'

const refName = 'AbsoluteTrend'

const rawDateFormat = 'YYYY-MM-DD'
const dateFormat = 'YYYY-MM'

const CheckboxGroup = Checkbox.Group

const getMaCalculator = (values) => (dayCount) => {
  const result = []
  for (let i = 0, len = values.length; i < len; i++) {
    if (i < dayCount) {
      result.push('-')
      continue
    }
    let sum = 0
    for (let j = 0; j < dayCount; j++) {
      sum += values[i - j]
    }
    result.push(sum / dayCount)
  }
  return result
}

const getOption = (trend) => {
  const calculateMA = getMaCalculator(trend.values)
  const legend = ['月线', 'MA3', 'MA5']
  return {
    title: {
      text: '绝对趋势',
      left: 100
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: legend
    },
    grid: {
      left: '10%',
      right: '10%',
      bottom: '15%'
    },
    xAxis: {
      type: 'category',
      data: trend.categoryData,
      scale: true,
      boundaryGap: false,
      axisLine: {onZero: false},
      splitLine: {show: false},
      splitNumber: 20,
      min: 'dataMin',
      max: 'dataMax'
    },
    yAxis: {
      scale: true,
      splitArea: {
        show: true
      }
    },
    dataZoom: [
      {
        type: 'inside',
        start: 50,
        end: 100
      },
      {
        show: true,
        type: 'slider',
        y: '90%',
        start: 50,
        end: 100
      }
    ],
    series: [
      {
        name: '月线',
        type: 'line',
        data: calculateMA(1),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      },
      {
        name: 'MA3',
        type: 'line',
        data: calculateMA(3),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      },
      {
        name: 'MA5',
        type: 'line',
        data: calculateMA(5),
        smooth: true,
        lineStyle: {
          normal: {opacity: 0.5}
        }
      }
    ]
  }
}

const topicName = (index) => (`主题${index + 1}`)

const transformData = (rawData) => {
  const totalTrend = {}
  const topicTrend = []

  rawData.forEach(data => {
    const date = moment(data.date, rawDateFormat).format(dateFormat)
    totalTrend[date] = _.get(totalTrend, date, 0) + 1
    const lda = data.lda
    const topic = lda.indexOf(Math.max(...lda))
    if (_.isEmpty(topicTrend[topic])) {
      topicTrend[topic] = {}
      topicTrend[topic][date] = 1
    } else {
      topicTrend[topic][date] = _.get(topicTrend[topic], date, 0) + 1
    }
  })

  const categoryData = []
  const topicsName = topicTrend.map((topic, index) => (topicName(index)))
  const topicValues = {}
  topicsName.forEach(topicName => { topicValues[topicName] = [] })

  _.forIn(totalTrend, (totalAmount, date) => {
    categoryData.push(date)
    topicTrend.forEach((topic, index) => {
      topicValues[topicName(index)].push(_.get(topic, date, 0) / totalAmount)
    })
  })
  return {categoryData, topicValues, topicsName}
}

export default class AbsoluteTrend extends React.Component {
  constructor () {
    super()
    this.state = {
      categoryData: [],
      topicValues: [],
      checkedList: [],
      topicsName: [],
      indeterminate: true,
      checkAll: false
    }
    fetch(`${serverAddress}/lda-doc`, { method: 'GET' })
      .then(checkStatus)
      .then((res) => (res.json()))
      .then((doc) => {
        const data = transformData(doc)
        this.setState({
          ...this.state,
          checkedList: [data.topicsName[0]],
          categoryData: data.categoryData,
          topicValues: data.topicValues,
          topicsName: data.topicsName
        })
      }) // todo draw
  }

  isDataLoaded () {
    return !_.isEmpty(this.state.topicsName)
  }

  componentDidMount () {
    this.myChart = echarts.init(this.refs[refName])
  }

  @autobind
  onChange (checkedList) {
    const plainOptions = this.state.topicsName
    this.setState({
      ...this.state,
      checkedList,
      indeterminate: !!checkedList.length && (checkedList.length < plainOptions.length),
      checkAll: checkedList.length === plainOptions.length
    })
  }

  @autobind
  onCheckAllChange (e) {
    this.setState({
      ...this.state,
      checkedList: e.target.checked ? this.state.topicsName : [],
      indeterminate: false,
      checkAll: e.target.checked
    })
  }

  @autobind
  drawAbsoluteTrend () {
    const option = getOption(this.state.trend)
    this.myChart.setOption(option)
  }

  @autobind
  drawCheckbox () {
    return

        <Checkbox
          indeterminate={this.state.indeterminate}
          onChange={this.onCheckAllChange}
          checked={this.state.checkAll}
        >
          全选
        </Checkbox>

      <CheckboxGroup options={this.state.topicsName} value={this.state.checkedList} onChange={this.onChange} />

  }

  render () {
    return

      {this.isDataLoaded()
        ? this.drawCheckbox()
        : <Loading />}

  }
}
<|endoftext|>


<commit_before>gAudio = (function(context) {
  AudioChannel = function() {
    this.gain = context.createGain();
    this.gain.gain.value = 0;
    this.gain.connect(context.destination);

    return this;
  }
  AudioChannel.prototype.start = function(freq, delay) {
    var start = context.currentTime;
    if (typeof delay === 'number') start += delay;
    this.gain.gain.linearRampToValueAtTime(0, start);
    this.gain.gain.linearRampToValueAtTime(0.1, start + 0.01);
    this.osc = context.createOscillator();
    this.osc.connect(this.gain);
    if (freq > 0) this.osc.frequency.value = freq;
    this.osc.start(start);
  }
  AudioChannel.prototype.stop = function(delay) {
    this.osc.stop(delay);
  }

  return {
    eChan1: new AudioChannel(),
    mChan1: new AudioChannel(),
    startBolt: function() {
      var now = context.currentTime;
      this.eChan1.start(now);
      this.eChan1.osc.frequency.linearRampToValueAtTime(1200, now);
      this.eChan1.osc.frequency.linearRampToValueAtTime(400, now + 0.1);
      this.eChan1.gain.gain.linearRampToValueAtTime(0.1, now + 0.1);
      this.eChan1.gain.gain.linearRampToValueAtTime(0, now + 0.11);
      this.eChan1.stop(now + 0.11);
    },
    playNote: function(chan, note, octave, start, duration) {
      var base;
      switch (note) {
        case 'c'  : base = 16.35; break;
        case 'db' : base = 17.32; break;
        case 'd'  : base = 18.35; break;
        case 'eb' : base = 19.45; break;
        case 'e'  : base = 20.60; break;
        case 'f'  : base = 21.83; break;
        case 'gb' : base = 23.12; break;
        case 'g'  : base = 24.50; break;
        case 'ab' : base = 25.96; break;
        case 'a'  : base = 27.50; break;
        case 'bb' : base = 29.14; break;
        case 'b'  : base = 30.87; break;
      }
      this['mChan' + chan].start(base * Math.pow(2, octave), start);
      this['mChan' + chan].stop(context.currentTime + start + duration);
    },
    playSong: function(song) {
      var start = 0;
      song.forEach(function(voice) {
        voice.forEach(function(note) {
          this.playNote(note[0], note[1], note[2], start, note[3]);
          start += note[3];
        }, this);
      }, this);
    }
  }
})(new AudioContext());

var titleSong = [[
  [1, 'c', 5, 0.2],
  [1, 'd', 5, 0.2],
  [1, 'e', 5, 0.4],
  [1, 'b', 5, 0.4],
  [1, 'a', 5, 0.2],
  [1, 'gb',5, 0.2],
  [1, 'a', 5, 0.4],
  [1, 'g', 5, 0.2],
  [1, 'e', 5, 0.2],
  [1, 'g', 5, 0.4],
  [1, 'gb',5, 0.4],
]];
<commit_msg>Update gAudio.playSong to automatically assign voices<commit_after>gAudio = (function(context) {
  AudioChannel = function() {
    this.gain = context.createGain();
    this.gain.gain.value = 0;
    this.gain.connect(context.destination);

    return this;
  }
  AudioChannel.prototype.start = function(freq, delay) {
    var start = context.currentTime;
    if (typeof delay === 'number') start += delay;
    this.gain.gain.linearRampToValueAtTime(0, start);
    this.gain.gain.linearRampToValueAtTime(0.1, start + 0.01);
    this.osc = context.createOscillator();
    this.osc.connect(this.gain);
    if (freq > 0) this.osc.frequency.value = freq;
    this.osc.start(start);
  }
  AudioChannel.prototype.stop = function(delay) {
    this.osc.stop(delay);
  }

  return {
    eChan1: new AudioChannel(),
    mChan1: new AudioChannel(),
    startBolt: function() {
      var now = context.currentTime;
      this.eChan1.start(now);
      this.eChan1.osc.frequency.linearRampToValueAtTime(1200, now);
      this.eChan1.osc.frequency.linearRampToValueAtTime(400, now + 0.1);
      this.eChan1.gain.gain.linearRampToValueAtTime(0.1, now + 0.1);
      this.eChan1.gain.gain.linearRampToValueAtTime(0, now + 0.11);
      this.eChan1.stop(now + 0.11);
    },
    playNote: function(chan, note, octave, start, duration) {
      var base;
      switch (note) {
        case 'c'  : base = 16.35; break;
        case 'db' : base = 17.32; break;
        case 'd'  : base = 18.35; break;
        case 'eb' : base = 19.45; break;
        case 'e'  : base = 20.60; break;
        case 'f'  : base = 21.83; break;
        case 'gb' : base = 23.12; break;
        case 'g'  : base = 24.50; break;
        case 'ab' : base = 25.96; break;
        case 'a'  : base = 27.50; break;
        case 'bb' : base = 29.14; break;
        case 'b'  : base = 30.87; break;
      }
      this['mChan' + chan].start(base * Math.pow(2, octave), start);
      this['mChan' + chan].stop(context.currentTime + start + duration);
    },
    playSong: function(song) {
      var start = 0;
      song.forEach(function(voice, vIndex) {
        voice.forEach(function(note) {
          this.playNote(vIndex + 1, note[0], note[1], start, note[2]);
          start += note[2];
        }, this);
      }, this);
    }
  }
})(new AudioContext());

var titleSong = [[
  ['c', 5, 0.2],
  ['d', 5, 0.2],
  ['e', 5, 0.4],
  ['b', 5, 0.4],
  ['a', 5, 0.2],
  ['gb',5, 0.2],
  ['a', 5, 0.4],
  ['g', 5, 0.2],
  ['e', 5, 0.2],
  ['g', 5, 0.4],
  ['gb',5, 0.4],
]];
<|endoftext|>


<commit_before>var fs = require('fs');
var http = require('http');

var getRawBody = require('raw-body');

var GifDuplex = require('../lib/gif-duplex');

module.exports = function gifRepl (port) {

  // Keep track of array of connections
  var connections = [];

  var app = http.createServer(function (req, res) {
    console.log('Request received');

    if (req.method === 'POST') {
      writeTextToConnections(req, res);
    } else {
      openNewGif(req, res);
    }
  });

  function openNewGif(req, res) {
    res.writeHead(200, {
      'connection': 'keep-alive',
      'content-type': 'image/gif',
      'transfer-encoding': 'chunked'
    });
    var gifDuplex = new GifDuplex();

    gifDuplex.on('data', function (buff) {
      res.write(buff);
    });

    gifDuplex.on('end', function () {
      res.end();
    });

    connections.push(gifDuplex);
  }

  // TODO: Debug single quotes in URLs

  function writeTextToConnections(req, res) {
    // Parse in the body (up to 1mb)
    console.log('Parsing body');
    getRawBody(req, {
      expected: req.headers['content-length'],
      limit: 1 * 1024 * 1024 // 1 mb
    }, function (err, buffer) {
      console.log('Body parsed');
      // If there was an error (e.g. bad length, over length), respond poorly
      if (err) {
        res.writeHead(500, {
          'content-type': 'text/plain'
        });
        res.end('Content was not as expected');
      }

      // Write out our text to all connections
      var text = buffer.toString();
      console.log('Outputting: ' + text);
      connections.forEach(function writeToResponse (gifDuplex) {
        gifDuplex.writeTextFrame(text);
      });
      res.writeHead(204);
      res.end();
    });
  }

  app.listen(port);
  console.log('gifsockets server is listening at http://127.0.0.1:' + port + '/');
};

if (module.parent === null) {
  module.exports(7000);
}
<commit_msg>Optimizing image creation for server<commit_after>var fs = require('fs');
var http = require('http');

var getRawBody = require('raw-body');

var GifDuplex = require('../lib/gif-duplex');

module.exports = function gifRepl (port) {

  // Keep track of array of connections
  var connections = [];

  var app = http.createServer(function (req, res) {
    console.log('Request received');

    if (req.method === 'POST') {
      writeTextToConnections(req, res);
    } else {
      openNewGif(req, res);
    }
  });

  function openNewGif(req, res) {
    res.writeHead(200, {
      'connection': 'keep-alive',
      'content-type': 'image/gif',
      'transfer-encoding': 'chunked'
    });
    var gifDuplex = new GifDuplex();

    gifDuplex.on('data', function (buff) {
      res.write(buff);
    });

    gifDuplex.on('end', function () {
      res.end();
    });

    connections.push(gifDuplex);
  }

  // TODO: Debug single quotes in URLs

  function writeTextToConnections(req, res) {
    // Parse in the body (up to 1mb)
    console.log('Parsing body');
    getRawBody(req, {
      expected: req.headers['content-length'],
      limit: 1 * 1024 * 1024 // 1 mb
    }, function (err, buffer) {
      console.log('Body parsed');
      // If there was an error (e.g. bad length, over length), respond poorly
      if (err) {
        res.writeHead(500, {
          'content-type': 'text/plain'
        });
        res.end('Content was not as expected');
      }

      // Write out our text to all connections
      var text = buffer.toString();
      console.log('Outputting: ' + text);
      if (connections.length) {
        connections[0].getTextFrameData(text, function (err, dataArr) {
          connections.forEach(function writeToResponse (gifDuplex) {
            gifDuplex.writeImageData(dataArr);
          });

          res.writeHead(204);
          res.end();
        });
      }
    });
  }

  app.listen(port);
  console.log('gifsockets server is listening at http://127.0.0.1:' + port + '/');
};

if (module.parent === null) {
  module.exports(7000);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

const {
  classes: Cc,
  interfaces: Ci,
  utils: Cu,
  results: Cr,
  Constructor, ctor
} = Components;

const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});

const ChromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
const MemoryReporterManager = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
const ResProtoHandler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
const MainThread = Services.tm.mainThread;

function _(id) {
  return document.body.getAttribute("data-" + id);
}

function runSoon(f) MainThread.dispatch(f, 0);
function minimizeMemoryUsage(callback) {
  function notify(i) {
    Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
    if (--i) {
      runSoon(notify.bind(null, i));
    }
    else if (callback) {
      runSoon(callback);
    }
  }
  if ("minimizeMemoryUsage" in MemoryReporterManager) {
    MemoryReporterManager.minimizeMemoryUsage(callback);
  }
  else {
    notify(3);
  }
}

function formatBytes(b) {
  if (b < 900) return b.toFixed(0) + " bytes";
  b /= 1024;
  if (b < 900) return b.toFixed(1) + " KB";
  b /= 1024;
  if (b < 900) return b.toFixed(2) + " MB";
  b /= 1024;
  return b.toFixed(3) + " GB";
}

function sortResults(a, b) {
  // size descending
  let rv = b.bytes - a.bytes;
  if (!rv) {
    // else name ascending
    rv = a.name < b.name ? -1 : 1;
  }
  return rv;
}

const resolveAboutURI = (function() {
  let resolved = new Map();
  return function resolveAboutURI(uri) {
    let mod = uri.path.replace(/#\?.*$/i, "");
    let rv = resolved.get(mod);
    if (!rv) {
      let c = Services.io.newChannelFromURI(uri);
      rv = c.URI.clone();
      if (rv.equals(uri)) {
        throw new Error("cannot resolve about URI");
      }
      resolved.set(mod, rv);
    }
    return rv;
  };
})();

function resolveURI(uri) {
  switch (uri.scheme) {
  case "jar":
  case "file":
    if (uri instanceof Ci.nsIJARURI) {
      return resolveURI(uri.JARFile);
    }
    return uri;
  case "chrome":
    return resolveURI(ChromeRegistry.convertChromeURL(uri));
  case "resource":
    return resolveURI(Services.io.newURI(ResProtoHandler.resolveURI(uri), null, null));
  case "about":
    if (uri.spec == "about:blank") {
      // hack: also map about:blank... to the app
      return resolveURI(resolveAboutURI(Services.io.newURI("about:memory", null, null)));
    }
    return resolveURI(resolveAboutURI(uri));
  case "view-source":
    return resolveURI(Services.io.newURI(uri.path, null, null));
  default:
    throw new Error("cannot handle");
  }
}

function $(id) document.getElementById(id);
function $e(tag, attrs, text) {
  let e = document.createElement(tag);
  if (attrs) {
    for (let [k,v] in Iterator(attrs)) {
      e.setAttribute(k, v);
    }
  }
  if (text) {
    e.textContent = text;
  }
  return e;
}
function process(addons) {
  const known = [];
  const compartments = Object.create(null);;
  const re_jscompartment = /^explicit\/.*?(?:\/non-window-global|js-non-window)\/.*?\/compartment\((.*?)\)/;
  const re_windowobject = /^explicit\/(?:.*\/)?window-objects\/top\((.*?), id=\d+\)\/active\//;
  const re_worker = /^explicit\/(?:.*\/)?workers\/workers\(\)\/worker\((.*?), 0x[\da-f]+\)/;
  const re_explicit = /^explicit\//;
  const re_compartment = /^(\[System Principal\], )?(?:in.*?\?ownedBy=)?(.+?)(?: \(from: (.+?)(?::\d+)?)?$/;
  const re_schemes = /^(?:about|chrome|file|jar|resource)/;
  let rss = 0;

  function handleReport(process, path, kind, units, amount, description) {
    if (path == "resident") {
      rss = amount;
      return;
    }
    let m, spec;
    if (m = path.match(re_jscompartment)) {
      m = m[1].match(re_compartment);
      let syscomp = !!m[1];
      spec = m[2];
      if (m[3] && (!syscomp || !re_schemes.test(spec))) {
        spec = m[3].split(" -> ").pop();
      }
    }
    else if (m = path.match(re_windowobject)) {
      spec = m[1];
    }
    else if (m = path.match(re_worker)) {
      spec = m[1];
    }

    if (!spec) {
      return;
    }
    spec = spec.replace(/\\/g, "/").trim();
    try {
      if (spec in compartments) {
        compartments[spec] += amount;
      }
      else {
        compartments[spec] = amount;
      }
    }
    catch (ex) {
      console.error(spec.toSource(), ex);
    }
  }

  function mapSpecToAddon(spec, bytes) {
    if (/omni\.ja$|\.apk$/.test(spec)) {
      known[0].bytes += bytes;
      return true;
    }
    for (let [,k] in Iterator(known)) {
      if (spec.lastIndexOf(k.spec, 0) == 0) {
        k.bytes += bytes;
        return true;
      }
    }
    return false;
  }

  function process() {
    // map reports to addons
    for (let [c, b] in Iterator(compartments)) {
      try {
        let spec = resolveURI(Services.io.newURI(c, null, null)).spec;
        if (!mapSpecToAddon(spec, b)) {
          throw new Error("not an addon uri:" + spec);
        }
      }
      catch (ex) {
        console.warn("failed to map", c, ex);
      }
    }

    // construct table
    known.sort(sortResults);
    let maxAddonBytes = 0;
    let totalAddons = known.reduce(function(p, e) {
      maxAddonBytes = Math.max(maxAddonBytes, e.bytes);
      return e.bytes + p;
    }, 0);

    let fragment = document.createDocumentFragment();
    let noteid = 0;
    for (let [,k] in Iterator(known)) {
      let tr = $e("tr");
      if (!k.addon.isActive) {
        tr.className = "disabled";
      }
      let tdn = $e("td");

      let icon = k.addon.icon64URL || k.addon.iconURL || "chrome://mozapps/skin/extensions/extensionGeneric.png";
      icon = $e("img", {"src": icon});
      let iconBox = $e("div", {"class": "icon"});
      let figure = $e("figure", {"class": "icon"});
      iconBox.appendChild(icon);
      figure.appendChild(iconBox);
      tdn.appendChild(figure);

      let footnotes;
      if (k.footnotes) {
        footnotes = document.createDocumentFragment();
        for (let [,note] in Iterator(k.footnotes)) {
          let id = ++noteid;
          let fn = $e("sup");
          // hack: need to construct the absolute uri ourselves in about:
          fn.appendChild($e("a", {"href": "about:addons-memory#fn_" + id}, id.toFixed(0)));
          footnotes.appendChild(fn);
          let text = $e("p", {"class": "fn", "id": "fn_" + id}, note);
          let anc = $e("sup", null, "[" + id + "] ");
          text.insertBefore(anc, text.firstChild);
          document.body.appendChild(text);
        }
      }

      let pname = $e("p", {"class": "name"});
      if (k.addon.homepageURL) {
        pname.appendChild($e("a", {"target":"_blank", "href": k.addon.homepageURL}, k.addon.name));
      }
      else {
        pname.textContent = k.addon.name;
      }
      if (footnotes) {
        pname.appendChild(footnotes);
      }
      tdn.appendChild(pname);

      tdn.appendChild($e("p", {"class": "creator"}, _("by") + " " + k.addon.creator));
      tdn.appendChild($e("p", {"class": "id"}, k.addon.id));
      tr.appendChild(tdn);
      tr.appendChild($e("td", {"data-value": k.bytes}, formatBytes(k.bytes)));

      let pa = k.bytes / totalAddons;
      let spa = (pa * 100.0).toFixed(1) + "%";
      let pe = k.bytes / rss;
      let spe = (pe * 100.0).toFixed(1) + "%";
      let scale = (k.bytes / maxAddonBytes * 100.0).toFixed(1) + "%";

      tr.appendChild($e("td", {"data-value": pa}, spa));
      tr.appendChild($e("td", {"data-value": pe}, spe));
      let progress = $e("div", {"class": "bar"});
      progress.style.width = scale;
      let tdp = $e("td");
      tdp.appendChild(progress);
      tr.appendChild(tdp);
      fragment.appendChild(tr);
    }
    let tr = $e("tr", {"class": "total"});
    tr.appendChild($e("td", null, "Total"));
    tr.appendChild($e("td", null, formatBytes(totalAddons)));
    tr.appendChild($e("td", null, "100%"));
    tr.appendChild($e("td", null, (totalAddons / rss * 100.0).toFixed(1) + "%"));
    fragment.appendChild(tr);

    $("tbody").appendChild(fragment);

    let (l = $("loading")) {
      l.parentNode.removeChild(l);
    }
  }

  try {
    // Forcefeed the "Application" add-on
    {
      let appuri = resolveURI(Services.io.newURI("about:config", null, null));
      let iconURL = "chrome://branding/content/icon64.png"
      try {
        if (!/omni\.ja|\.apk$/.test(appuri.spec)) {
          appuri.path = appuri.path.replace("chrome/toolkit/content/global/global.xul", "");
        }
      }
      catch (ex) {
        console.log("failed to get proper appuri; assuming omnijar");
      }
      if (/\.apk$/.test(appuri.spec)) {
        iconURL = "chrome://branding/content/favicon64.png"
      }
      let addon = {
        name: "Application",
        isActive: true,
        id: Services.appinfo.ID,
        creator: "Mozilla",
        iconURL: iconURL
        };
      try {
        let branding = Services.strings.createBundle("chrome://branding/locale/brand.properties");
        addon.name = branding.GetStringFromName("brandFullName");
        addon.creator = branding.GetStringFromName("vendorShortName");
      }
      catch (ex) {
        console.error("failed to get branding", ex);
      }
      known.push({
        addon: addon,
        base: appuri,
        spec: appuri.spec,
        bytes: 0,
        footnotes: [_("footnote-locations")]
        });
    }

    // process addons
    for (let [,a] in Iterator(addons)) {
      try {
        let base = resolveURI(a.getResourceURI(".").cloneIgnoringRef());
        let notes;
        if (a.id == "about-addons-memory@tn123.org") {
          notes = [_("footnote-thisaddon")];
        }
        known.push({
          addon: a,
          base: base,
          spec: base.spec,
          bytes: 0,
          footnotes: notes
          });
      }
      catch (ex) {
        console.warn("addon not supported", a.id);
      }
    }

    // process reports
    if ("nsIMemoryMultiReporter" in Ci) {
      console.log("taking uni");
      let e = MemoryReporterManager.enumerateReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryReporter) {
          handleReport(null, r.path, r.kind, r.units, r.amount);
        }
      }
      e = MemoryReporterManager.enumerateMultiReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryMultiReporter) {
          r.collectReports(handleReport, null);
        }
      }
      process();
    }
    else if ("enumerateReporters" in MemoryReporterManager) {
      console.log("taking no-uni");
      let e = MemoryReporterManager.enumerateReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryReporter) {
          r.collectReports(handleReport, null);
        }
      }
      process();
    }
    else {
      console.log("taking getReports");
      if (MemoryReporterManager.getReports.length == 5) {
        MemoryReporterManager.getReports(handleReport, null, process, null, false);
      }
      else {
        MemoryReporterManager.getReports(handleReport, null, process, null);
      }
    }

  }
  catch (ex) {
    console.error(ex);
  }
}

addEventListener("load", function load() {
  removeEventListener("load", load, false);
  Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager.getAllAddons(process);
}, false);

/* vim: set et ts=2 sw=2 : */
<commit_msg>Latest nightly compat<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

const {
  classes: Cc,
  interfaces: Ci,
  utils: Cu,
  results: Cr,
  Constructor, ctor
} = Components;

const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});

const ChromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
const MemoryReporterManager = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
const ResProtoHandler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
const MainThread = Services.tm.mainThread;

function _(id) {
  return document.body.getAttribute("data-" + id);
}

function runSoon(f) MainThread.dispatch(f, 0);
function minimizeMemoryUsage(callback) {
  function notify(i) {
    Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
    if (--i) {
      runSoon(notify.bind(null, i));
    }
    else if (callback) {
      runSoon(callback);
    }
  }
  if ("minimizeMemoryUsage" in MemoryReporterManager) {
    MemoryReporterManager.minimizeMemoryUsage(callback);
  }
  else {
    notify(3);
  }
}

function formatBytes(b) {
  if (b < 900) return b.toFixed(0) + " bytes";
  b /= 1024;
  if (b < 900) return b.toFixed(1) + " KB";
  b /= 1024;
  if (b < 900) return b.toFixed(2) + " MB";
  b /= 1024;
  return b.toFixed(3) + " GB";
}

function sortResults(a, b) {
  // size descending
  let rv = b.bytes - a.bytes;
  if (!rv) {
    // else name ascending
    rv = a.name < b.name ? -1 : 1;
  }
  return rv;
}

const resolveAboutURI = (function() {
  let resolved = new Map();
  return function resolveAboutURI(uri) {
    let mod = uri.path.replace(/#\?.*$/i, "");
    let rv = resolved.get(mod);
    if (!rv) {
      let c = Services.io.newChannelFromURI(uri);
      rv = c.URI.clone();
      if (rv.equals(uri)) {
        throw new Error("cannot resolve about URI");
      }
      resolved.set(mod, rv);
    }
    return rv;
  };
})();

function resolveURI(uri) {
  switch (uri.scheme) {
  case "jar":
  case "file":
    if (uri instanceof Ci.nsIJARURI) {
      return resolveURI(uri.JARFile);
    }
    return uri;
  case "chrome":
    return resolveURI(ChromeRegistry.convertChromeURL(uri));
  case "resource":
    return resolveURI(Services.io.newURI(ResProtoHandler.resolveURI(uri), null, null));
  case "about":
    if (uri.spec == "about:blank") {
      // hack: also map about:blank... to the app
      return resolveURI(resolveAboutURI(Services.io.newURI("about:memory", null, null)));
    }
    return resolveURI(resolveAboutURI(uri));
  case "view-source":
    return resolveURI(Services.io.newURI(uri.path, null, null));
  default:
    throw new Error("cannot handle");
  }
}

function $(id) document.getElementById(id);
function $e(tag, attrs, text) {
  let e = document.createElement(tag);
  if (attrs) {
    for (let [k,v] in Iterator(attrs)) {
      e.setAttribute(k, v);
    }
  }
  if (text) {
    e.textContent = text;
  }
  return e;
}
function process(addons) {
  const known = [];
  const compartments = Object.create(null);;
  const re_jscompartment = /^explicit\/.*?(?:\/non-window-global|js-non-window)\/.*?\/compartment\((.*?)\)/;
  const re_windowobject = /^explicit\/(?:.*\/)?window-objects\/top\((.*?), id=\d+\)\/active\//;
  const re_worker = /^explicit\/(?:.*\/)?workers\/workers\(\)\/worker\((.*?), 0x[\da-f]+\)/;
  const re_explicit = /^explicit\//;
  const re_compartment = /^(\[System Principal\], )?(?:in.*?\?ownedBy=)?(.+?)(?: \(from: (.+?)(?::\d+)?)?$/;
  const re_schemes = /^(?:about|chrome|file|jar|resource)/;
  let rss = 0;

  function handleReport(process, path, kind, units, amount, description) {
    if (path == "resident") {
      rss = amount;
      return;
    }
    let m, spec;
    if (m = path.match(re_jscompartment)) {
      m = m[1].match(re_compartment);
      let syscomp = !!m[1];
      spec = m[2];
      if (m[3] && (!syscomp || !re_schemes.test(spec))) {
        spec = m[3].split(" -> ").pop();
      }
    }
    else if (m = path.match(re_windowobject)) {
      spec = m[1];
    }
    else if (m = path.match(re_worker)) {
      spec = m[1];
    }

    if (!spec) {
      return;
    }
    spec = spec.replace(/\\/g, "/").trim();
    try {
      if (spec in compartments) {
        compartments[spec] += amount;
      }
      else {
        compartments[spec] = amount;
      }
    }
    catch (ex) {
      console.error(spec.toSource(), ex);
    }
  }

  function mapSpecToAddon(spec, bytes) {
    if (/omni\.ja$|\.apk$/.test(spec)) {
      known[0].bytes += bytes;
      return true;
    }
    for (let [,k] in Iterator(known)) {
      if (spec.lastIndexOf(k.spec, 0) == 0) {
        k.bytes += bytes;
        return true;
      }
    }
    return false;
  }

  function process() {
    // map reports to addons
    for (let [c, b] in Iterator(compartments)) {
      try {
        let spec = resolveURI(Services.io.newURI(c, null, null)).spec;
        if (!mapSpecToAddon(spec, b)) {
          throw new Error("not an addon uri:" + spec);
        }
      }
      catch (ex) {
        console.warn("failed to map", c, ex);
      }
    }

    // construct table
    known.sort(sortResults);
    let maxAddonBytes = 0;
    let totalAddons = known.reduce(function(p, e) {
      maxAddonBytes = Math.max(maxAddonBytes, e.bytes);
      return e.bytes + p;
    }, 0);

    let fragment = document.createDocumentFragment();
    let noteid = 0;
    for (let [,k] in Iterator(known)) {
      let tr = $e("tr");
      if (!k.addon.isActive) {
        tr.className = "disabled";
      }
      let tdn = $e("td");

      let icon = k.addon.icon64URL || k.addon.iconURL || "chrome://mozapps/skin/extensions/extensionGeneric.svg";
      icon = $e("img", {"src": icon});
      let iconBox = $e("div", {"class": "icon"});
      let figure = $e("figure", {"class": "icon"});
      iconBox.appendChild(icon);
      figure.appendChild(iconBox);
      tdn.appendChild(figure);

      let footnotes;
      if (k.footnotes) {
        footnotes = document.createDocumentFragment();
        for (let [,note] in Iterator(k.footnotes)) {
          let id = ++noteid;
          let fn = $e("sup");
          // hack: need to construct the absolute uri ourselves in about:
          fn.appendChild($e("a", {"href": "about:addons-memory#fn_" + id}, id.toFixed(0)));
          footnotes.appendChild(fn);
          let text = $e("p", {"class": "fn", "id": "fn_" + id}, note);
          let anc = $e("sup", null, "[" + id + "] ");
          text.insertBefore(anc, text.firstChild);
          document.body.appendChild(text);
        }
      }

      let pname = $e("p", {"class": "name"});
      if (k.addon.homepageURL) {
        pname.appendChild($e("a", {"target":"_blank", "href": k.addon.homepageURL}, k.addon.name));
      }
      else {
        pname.textContent = k.addon.name;
      }
      if (footnotes) {
        pname.appendChild(footnotes);
      }
      tdn.appendChild(pname);

      tdn.appendChild($e("p", {"class": "creator"}, _("by") + " " + k.addon.creator));
      tdn.appendChild($e("p", {"class": "id"}, k.addon.id));
      tr.appendChild(tdn);
      tr.appendChild($e("td", {"data-value": k.bytes}, formatBytes(k.bytes)));

      let pa = k.bytes / totalAddons;
      let spa = (pa * 100.0).toFixed(1) + "%";
      let pe = k.bytes / rss;
      let spe = (pe * 100.0).toFixed(1) + "%";
      let scale = (k.bytes / maxAddonBytes * 100.0).toFixed(1) + "%";

      tr.appendChild($e("td", {"data-value": pa}, spa));
      tr.appendChild($e("td", {"data-value": pe}, spe));
      let progress = $e("div", {"class": "bar"});
      progress.style.width = scale;
      let tdp = $e("td");
      tdp.appendChild(progress);
      tr.appendChild(tdp);
      fragment.appendChild(tr);
    }
    let tr = $e("tr", {"class": "total"});
    tr.appendChild($e("td", null, "Total"));
    tr.appendChild($e("td", null, formatBytes(totalAddons)));
    tr.appendChild($e("td", null, "100%"));
    tr.appendChild($e("td", null, (totalAddons / rss * 100.0).toFixed(1) + "%"));
    fragment.appendChild(tr);

    $("tbody").appendChild(fragment);

    {
      let l = $("loading");
      l.parentNode.removeChild(l);
    }
  }

  try {
    // Forcefeed the "Application" add-on
    {
      let appuri = resolveURI(Services.io.newURI("about:config", null, null));
      let iconURL = "chrome://branding/content/icon64.png"
      try {
        if (!/omni\.ja|\.apk$/.test(appuri.spec)) {
          appuri.path = appuri.path.replace("chrome/toolkit/content/global/global.xul", "");
        }
      }
      catch (ex) {
        console.log("failed to get proper appuri; assuming omnijar");
      }
      if (/\.apk$/.test(appuri.spec)) {
        iconURL = "chrome://branding/content/favicon64.png"
      }
      let addon = {
        name: "Application",
        isActive: true,
        id: Services.appinfo.ID,
        creator: "Mozilla",
        iconURL: iconURL
        };
      try {
        let branding = Services.strings.createBundle("chrome://branding/locale/brand.properties");
        addon.name = branding.GetStringFromName("brandFullName");
        addon.creator = branding.GetStringFromName("vendorShortName");
      }
      catch (ex) {
        console.error("failed to get branding", ex);
      }
      known.push({
        addon: addon,
        base: appuri,
        spec: appuri.spec,
        bytes: 0,
        footnotes: [_("footnote-locations")]
        });
    }

    // process addons
    for (let [,a] in Iterator(addons)) {
      try {
        let base = resolveURI(a.getResourceURI(".").cloneIgnoringRef());
        let notes;
        if (a.id == "about-addons-memory@tn123.org") {
          notes = [_("footnote-thisaddon")];
        }
        known.push({
          addon: a,
          base: base,
          spec: base.spec,
          bytes: 0,
          footnotes: notes
          });
      }
      catch (ex) {
        console.warn("addon not supported", a.id);
      }
    }

    // process reports
    if ("nsIMemoryMultiReporter" in Ci) {
      console.log("taking uni");
      let e = MemoryReporterManager.enumerateReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryReporter) {
          handleReport(null, r.path, r.kind, r.units, r.amount);
        }
      }
      e = MemoryReporterManager.enumerateMultiReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryMultiReporter) {
          r.collectReports(handleReport, null);
        }
      }
      process();
    }
    else if ("enumerateReporters" in MemoryReporterManager) {
      console.log("taking no-uni");
      let e = MemoryReporterManager.enumerateReporters();
      while (e.hasMoreElements()) {
        let r = e.getNext();
        if (r instanceof Ci.nsIMemoryReporter) {
          r.collectReports(handleReport, null);
        }
      }
      process();
    }
    else {
      console.log("taking getReports");
      if (MemoryReporterManager.getReports.length == 5) {
        MemoryReporterManager.getReports(handleReport, null, process, null, false);
      }
      else {
        MemoryReporterManager.getReports(handleReport, null, process, null);
      }
    }

  }
  catch (ex) {
    console.error(ex);
  }
}

addEventListener("load", function load() {
  removeEventListener("load", load, false);
  Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager.getAllAddons(process);
}, false);

/* vim: set et ts=2 sw=2 : */
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');

var rootDataPath = './data';

var getData = function(doneCallBack) {
	var filePath = rootDataPath + '/basic.json';
	var jsonReadCallBack = function(err, data){
		if (err) doneCallBack('Data readFile error ' + filePath);
		else {
			var jsonData = JSON.parse(data.toString());
			doneCallBack(jsonData);
		}
	};
	fs.readFile(filePath, jsonReadCallBack);
};

var setData = function(data) {
	var filePath = rootDataPath + '/basic.json';
	var writeFileCallBack = function (err) {
		if (err) console.log('error saving Data.json file ');
	};
	fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
};

module.exports.getData = getData;
module.exports.setData = setData;

<commit_msg>Tabs to spaces<commit_after>'use strict';

var fs = require('fs');

var rootDataPath = './data';

var getData = function(doneCallBack) {
  var filePath = rootDataPath + '/basic.json';
  var jsonReadCallBack = function(err, data){
    if (err) doneCallBack('Data readFile error ' + filePath);
    else {
      var jsonData = JSON.parse(data.toString());
      doneCallBack(jsonData);
    }
  };
  fs.readFile(filePath, jsonReadCallBack);
};

var setData = function(data) {
  var filePath = rootDataPath + '/basic.json';
  var writeFileCallBack = function (err) {
    if (err) console.log('error saving Data.json file ');
  };
  fs.writeFile(filePath, JSON.stringify(data, null, 2), writeFileCallBack);
};

module.exports.getData = getData;
module.exports.setData = setData;
<|endoftext|>