We'll extend our previous examples

We can now extend 05 - Include an IFrame.ipynb to pass data to the iframe using either the query string or using window.postMessage. In this case we'll use https://soasta.github.io/julia-d3-tutorial/d3/07-d3-external-data.html?data=<data> as our URL.

Our createIFrame and updateIFrame functions remain the same.


In [15]:
function createIFrame()
    displayid = "demo-iframe-" * string(rand())
    
    display(
        "text/html", 
        """
    <!-- First create an empty iframe that's 500px high and has this id -->
    <iframe
        id="$(displayid)"
        height="500"
        style="border:none;"
        src="about:blank">
    </iframe>


    <!-- Next create a JavaScript function with the same name as the node -->
    <script>
        window["$(displayid)"] = function(url) {
            var iframe = document.getElementById("$(displayid)");
            if(iframe) {
                iframe.width = iframe.parentNode.offsetWidth * 0.98;
                iframe.src = url;
            }
        };
    </script>
        """
    )
    
    return displayid
end


Out[15]:
createIFrame (generic function with 1 method)

Add Type to updateIFrame signature

Notice that we add a String Type for the updateIFrame method. This will allow us to overload it later


In [16]:
function updateIFrame(displayid::AbstractString, url::AbstractString)
    display(
        "text/html",
        """<script>window["$(displayid)"]("$(url)");</script>"""
    )
end


Out[16]:
updateIFrame (generic function with 2 methods)

Add window.postMessage

We now overload the updateIFrame method to accept a Numeric Array and pass that on to the iframe using window.postMessage


In [25]:
function updateIFrame(displayid::AbstractString, data::Array{Int64, 1})
    display(
        "text/html",
        """
        <script>
        (function() {
            var iframe = document.getElementById("$(displayid)");
            if(iframe) {
                iframe.contentWindow.postMessage($(JSON.json(data)), "*");
            }
        }())
        </script>
        """
    )
end


Out[25]:
updateIFrame (generic function with 3 methods)

Tying these together, we can draw and update the iframe


In [18]:
id = createIFrame()

# Note that we do not include the [] for data here since this is not JSON, it's just a csv
updateIFrame(id, "https://soasta.github.io/julia-d3-tutorial/d3/07-d3-external-data.html?data=36,90,168,370,589,867,951,873,838,752,637,542,479,359,303,291,199,186,146,119,115,100,77,90,67,753")


We can pass new data to the IFrame

By calling updateIFrame with a a data array, we can change what's displayed


In [26]:
updateIFrame(id, Int64[0,0,0,2,6,5,10,11,15,18,25,11,19,8,4,8,3,10,6,6,2,2,1,1,1,24])


DataFrame to IFrame

We can even get our DataFrame code to pass data to the IFrame


In [27]:
using DataFrames
df = readtable("data.csv");

# Function to set histogram thresholds after dropping outliers based on IQR
function getSymmetricThresholds(results::DataFrame; timer::Symbol=:timers_t_done)
    summary = summarystats(results[timer])
    fw  = (summary.q75-summary.q25)*1.5

    low = round(Int64, max(summary.min, summary.q25-fw))
    high = round(Int64, min(summary.max, summary.q75+fw))+1

    thresholds::Array{Int64, 1} = []

    nthresholds=25

    range = high - low

    for i in 0:nthresholds-1
        push!(thresholds, round(Int64, low + i * range/nthresholds))
    end

    push!(thresholds, high)
    if high < round(Int64, summary.max)
        push!(thresholds, round(Int64, summary.max))
    end

    return thresholds
end


Out[27]:
getSymmetricThresholds (generic function with 1 method)

In [32]:
thresholds = getSymmetricThresholds(df)

groups = by(
    df,
    :user_agent_family, 
    rows -> DataFrame(
        count = size(rows, 1),
        median = median(rows[:timers_t_done]),
        hist = JSON.json(hist(rows[:timers_t_done], thresholds)[2])
    )
)

sort!(groups, rev=true, cols=[:count])


Out[32]:
user_agent_familycountmedianhist
1Mobile Safari877754147.0[32,1018,4282,7212,8901,9018,7763,6621,5638,4906,4083,3472,2948,2340,2165,1890,1706,1601,1398,1157,1018,937,805,704,597,5562]
2Chrome530863129.0[65,2116,6133,7217,6356,5033,3894,3216,2735,2225,1788,1558,1398,1164,993,872,711,606,563,464,437,342,322,275,246,2357]
3IE353602862.0[30,1305,4636,5553,4614,3543,2714,2141,1811,1395,1151,971,782,688,581,412,350,335,274,253,201,186,156,106,93,1079]
4Chrome Mobile314776776.0[0,1,23,60,230,594,1106,1698,2232,2663,2709,2494,2268,2082,1793,1607,1356,1140,997,835,671,612,504,402,369,3031]
5Safari171162605.0[108,1339,2476,2686,2085,1532,1262,1032,875,598,424,385,366,310,199,180,171,122,110,74,55,72,65,36,42,512]
6Firefox119843412.0[14,372,1051,1392,1398,1255,1085,832,803,575,548,383,322,267,220,156,148,115,134,99,74,82,64,38,52,505]
7Edge61503187.0[3,151,632,843,800,633,513,434,353,272,225,182,149,122,104,88,72,74,54,42,62,39,43,26,24,210]
8Amazon Silk23237599.0[0,0,0,1,15,39,84,117,133,147,145,165,155,113,141,113,108,90,78,70,67,76,53,49,49,315]
9Chrome Mobile iOS19874257.0[0,22,86,184,182,198,179,132,107,101,82,69,60,48,42,36,37,39,39,37,26,21,18,31,17,194]
10Android Browser175211886.0[0,1,0,0,0,3,17,29,43,50,66,63,76,65,80,46,64,55,52,48,44,41,52,46,32,779]
11IE Mobile2266265.5[0,0,0,0,0,2,6,10,15,18,34,30,14,15,10,6,13,5,7,2,4,4,1,2,1,27]
12Firefox Mobile2048456.0[0,0,0,0,2,4,5,8,8,9,12,13,11,13,6,10,9,10,13,7,6,10,8,7,3,30]
13Opera12312211.0[0,0,1,2,2,4,9,6,3,5,4,4,4,1,4,1,4,1,2,0,1,0,3,2,1,59]
14Other864855.5[0,0,0,3,3,5,7,8,15,14,4,4,4,1,1,1,1,1,1,1,1,1,1,1,0,8]
15PhantomJS781660.5[0,7,27,26,10,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
16(Unknown)733740.0[0,1,8,9,6,5,7,5,0,2,1,2,4,0,0,3,1,5,3,1,2,2,0,1,0,5]
17BlackBerry WebKit438684.0[0,0,0,0,1,1,1,0,2,1,2,1,3,3,4,1,3,0,2,1,0,2,2,0,1,12]
18Chrome Frame374067.0[0,0,1,4,4,5,3,4,4,2,1,0,1,0,2,0,1,1,0,1,0,1,0,0,0,2]
19Pale Moon (Firefox Variant)184797.5[0,0,0,1,1,2,0,4,1,1,2,4,0,1,0,0,0,1,0,0,0,0,0,0,0,0]
20AOL154857.0[0,0,1,1,1,1,1,0,2,2,0,1,0,1,2,0,0,0,0,0,0,0,0,0,0,2]
21Yandex Browser138513.0[0,0,0,0,0,0,3,0,0,1,1,0,0,0,1,0,1,1,0,2,0,0,0,1,0,2]
22Halebot104654.0[0,0,0,2,1,1,0,0,2,1,0,0,1,0,0,0,0,2,0,0,0,0,0,0,0,0]
23Iron102738.0[0,0,0,1,3,3,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
24Firefox Beta910278.0[0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,1,3]
25Opera Mobile912235.0[0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,2,0,3]
26Opera Mini73835.0[0,0,0,1,1,0,1,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
27Maxthon63961.0[0,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0]
28Chromium52772.0[0,0,0,0,2,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0]
29Puffin5922.0[0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
30Opera Coast36091.0[0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0]
&vellip&vellip&vellip&vellip&vellip

In [29]:
groups[groups[:user_agent_family] .== "Firefox", :hist][1]


Out[29]:
"[14,372,1051,1392,1398,1255,1085,832,803,575,548,383,322,267,220,156,148,115,134,99,74,82,64,38,52,505]"

In [30]:
# Take the histogram (string) out of the dataframe, and convert it to a numeric array
groupdata = JSON.parse(groups[groups[:user_agent_family] .== "Firefox", :hist][1])


# Pass that array to the IFrame
updateIFrame(id, groupdata)


The output shows up in the iframe above, so scroll up to see it

In fact, we could draw multiple histograms, one for each of the groups that we created


In [33]:
for i in 1:min(10, size(groups, 1))
    local id = createIFrame()
    local data = groups[i, :hist]
    updateIFrame(id, "https://soasta.github.io/julia-d3-tutorial/d3/07-d3-external-data.html?data=$(data)")

    display("text/html", """
    <p style="border-top: dashed 1px #ddd; border-bottom: solid 2px #000; padding-bottom: 3em;">
        <strong>$(groups[i, :user_agent_family]):</strong>
        <em>$(groups[i, :count])</em> records, median load time: <em>$(groups[i, :median])</em>ms
        </p>
        """
    )
end


Mobile Safari: 87775 records, median load time: 4147.0ms

Chrome: 53086 records, median load time: 3129.0ms

IE: 35360 records, median load time: 2862.0ms

Chrome Mobile: 31477 records, median load time: 6776.0ms

Safari: 17116 records, median load time: 2605.0ms

Firefox: 11984 records, median load time: 3412.0ms

Edge: 6150 records, median load time: 3187.0ms

Amazon Silk: 2323 records, median load time: 7599.0ms

Chrome Mobile iOS: 1987 records, median load time: 4257.0ms

Android Browser: 1752 records, median load time: 11886.0ms


In [ ]: