diff options
Diffstat (limited to 'web/src/vendor/benchmark/plugin/ui.browserscope.js')
-rw-r--r-- | web/src/vendor/benchmark/plugin/ui.browserscope.js | 1052 |
1 files changed, 0 insertions, 1052 deletions
diff --git a/web/src/vendor/benchmark/plugin/ui.browserscope.js b/web/src/vendor/benchmark/plugin/ui.browserscope.js deleted file mode 100644 index 01905bde..00000000 --- a/web/src/vendor/benchmark/plugin/ui.browserscope.js +++ /dev/null @@ -1,1052 +0,0 @@ -(function(window, document) { - - /** Cache used by various methods */ - var cache = { - 'counter': 0, - 'lastAction': 'load', - 'lastChart': 'bar', - 'lastFilterBy': 'all', - 'responses': { /* 'all': null, 'desktop': null, 'major': null, ... */ }, - 'timers': { /* 'cleanup': null, 'load': null, 'post': null, ... */ }, - 'trash': createElement('div') - }; - - /** - * Used to filter Browserscope results by browser category. - * - * @see http://www.browserscope.org/user/tests/howto#urlparams - */ - var filterMap = { - 'all': 3, - 'desktop': 'top-d', - 'family': 0, - 'major': 1, - 'minor': 2, - 'mobile': 'top-m', - 'popular': 'top', - 'prerelease': 'top-d-e' - }; - - /** Used to resolve a value's internal [[Class]] */ - var toString = {}.toString; - - /** - * The `uaToken` is prepended to the value of the data cell of the Google - * visualization data table object that matches the user's browser name. After - * the chart is rendered the element containing the `uaToken` is assigned the - * `ui.browserscope.uaClass` class name to allow for the creation of a visual - * indicator to help the user more easily find their browser's results. - */ - var uaToken = '\u2028'; - - /** Math shortcuts */ - var floor = Math.floor, - max = Math.max, - min = Math.min; - - /** Utility shortcuts */ - var each = Benchmark.each, - extend = Benchmark.extend, - filter = Benchmark.filter, - forOwn = Benchmark.forOwn, - formatNumber = Benchmark.formatNumber, - hasKey = Benchmark.hasKey, - indexOf = Benchmark.indexOf, - interpolate = Benchmark.interpolate, - invoke = Benchmark.invoke, - map = Benchmark.map, - reduce = Benchmark.reduce; - - /*--------------------------------------------------------------------------*/ - - /** - * Registers an event listener. - * - * @private - * @param {Element} element The element. - * @param {String} eventName The name of the event to listen to. - * @param {Function} handler The event handler. - * @returns {Element} The element. - */ - function addListener(element, eventName, handler) { - if ((element = typeof element == 'string' ? query(element)[0] : element)) { - if (typeof element.addEventListener != 'undefined') { - element.addEventListener(eventName, handler, false); - } else if (typeof element.attachEvent != 'undefined') { - element.attachEvent('on' + eventName, handler); - } - } - return element; - } - - /** - * Shortcut for `document.createElement()`. - * - * @private - * @param {String} tagName The tag name of the element to create. - * @param {String} name A name to assign to the element. - * @param {Document|Element} context The document object used to create the element. - * @returns {Element} Returns a new element. - */ - function createElement(tagName, name, context) { - var result; - name && name.nodeType && (context = name, name = 0); - context = context ? context.ownerDocument || context : document; - name || (name = ''); - - try { - // set name attribute for IE6/7 - result = context.createElement('<' + tagName + ' name="' + name + '">'); - } catch(e) { - (result = context.createElement(tagName)).name = name; - } - return result; - } - - /** - * Creates a new style element. - * - * @private - * @param {String} cssText The css text of the style element. - * @param {Document|Element} context The document object used to create the element. - * @returns {Element} Returns the new style element. - */ - function createStyleSheet(cssText, context) { - // use a text node, "x", to work around innerHTML issues with style elements - // http://msdn.microsoft.com/en-us/library/ms533897(v=vs.85).aspx#1 - var div = createElement('div', context); - div.innerHTML = 'x<style>' + cssText + '</style>'; - return div.lastChild; - } - - /** - * Gets the text content of an element. - * - * @private - * @param {Element} element The element. - * @returns {String} The text content of the element. - */ - function getText(element) { - element = query(element)[0]; - return element && (element.textContent || element.innerText) || ''; - } - - /** - * Injects a script into the document. - * - * @private - * @param {String} src The external script source. - * @param {Object} sibling The element to inject the script after. - * @param {Document} context The document object used to create the script element. - * @returns {Object} The new script element. - */ - function loadScript(src, sibling, context) { - context = sibling ? sibling.ownerDocument || [sibling, sibling = 0][0] : context; - var script = createElement('script', context), - nextSibling = sibling ? sibling.nextSibling : query('script', context).pop(); - - script.src = src; - return (sibling || nextSibling).parentNode.insertBefore(script, nextSibling); - } - - /** - * Queries the document for elements by id or tagName. - * - * @private - * @param {String} selector The css selector to match. - * @param {Document|Element} context The element whose descendants are queried. - * @returns {Array} The array of results. - */ - function query(selector, context) { - var result = []; - selector || (selector = ''); - context = typeof context == 'string' ? query(context)[0] : context || document; - - if (selector.nodeType) { - result = [selector]; - } - else if (context) { - each(selector.split(','), function(selector) { - each(/^#/.test(selector) - ? [context.getElementById(selector.slice(1))] - : context.getElementsByTagName(selector), function(node) { - result.push(node); - }); - }); - } - return result; - } - - /** - * Set an element's innerHTML property. - * - * @private - * @param {Element} element The element. - * @param {String} html The HTML to set. - * @param {Object} object The template object used to modify the html. - * @returns {Element} The element. - */ - function setHTML(element, html, object) { - if ((element = query(element)[0])) { - element.innerHTML = interpolate(html, object); - } - return element; - } - - /** - * Displays a message in the "results" element. - * - * @private - * @param {String} text The text to display. - * @param {Object} object The template object used to modify the text. - */ - function setMessage(text, object) { - var me = ui.browserscope, - cont = me.container; - - if (cont) { - cont.className = 'bs-rt-message'; - setHTML(cont, text, object); - } - } - - /*--------------------------------------------------------------------------*/ - - /** - * Adds a style sheet to the current chart and assigns the `ui.browserscope.uaClass` - * class name to the chart element containing the user's browser name. - * - * @private - * @returns {Boolean} Returns `true` if the operation succeeded, else `false`. - */ - function addChartStyle() { - var me = ui.browserscope, - cssText = [], - context = frames[query('iframe', me.container)[0].name].document, - chartNodes = query('text,textpath', context), - uaClass = me.uaClass, - result = false; - - if (chartNodes.length) { - // extract CSS rules for `uaClass` - each(query('link,style'), function(node) { - // avoid access denied errors on external style sheets - // outside the same origin policy - try { - var sheet = node.sheet || node.styleSheet; - each(sheet.cssRules || sheet.rules, function(rule) { - if ((rule.selectorText || rule.cssText).indexOf('.' + uaClass) > -1) { - cssText.push(rule.style && rule.style.cssText || /[^{}]*(?=})/.exec(rule.cssText) || ''); - } - }); - } catch(e) { } - }); - - // insert custom style sheet - query('head', context)[0].appendChild( - createStyleSheet('.' + uaClass + '{' + cssText.join(';') + '}', context)); - - // scan chart elements for a match - each(chartNodes, function(node) { - var nextSibling; - if ((node.string || getText(node)).charAt(0) == uaToken) { - // for VML - if (node.string) { - // IE requires reinserting the element to render correctly - node.className = uaClass; - nextSibling = node.nextSibling; - node.parentNode.insertBefore(node.removeNode(), nextSibling); - } - // for SVG - else { - node.setAttribute('class', uaClass); - } - result = true; - } - }); - } - return result; - } - - /** - * Periodically executed callback that removes injected script and iframe elements. - * - * @private - */ - function cleanup() { - var me = ui.browserscope, - timings = me.timings, - timers = cache.timers, - trash = cache.trash, - delay = timings.cleanup * 1e3; - - // remove injected scripts and old iframes when benchmarks aren't running - if (timers.cleanup && !ui.running) { - // if expired, destroy the element to prevent pseudo memory leaks. - // http://dl.dropbox.com/u/513327/removechild_ie_leak.html - each(query('iframe,script'), function(element) { - var expire = +(/^browserscope-\d+-(\d+)$/.exec(element.name) || 0)[1] + max(delay, timings.timeout * 1e3); - if (new Date > expire || /browserscope\.org|google\.com/.test(element.src)) { - trash.appendChild(element); - trash.innerHTML = ''; - } - }); - } - // schedule another round - timers.cleanup = setTimeout(cleanup, delay); - } - - /** - * A simple data object cloning utility. - * - * @private - * @param {Mixed} data The data object to clone. - * @returns {Mixed} The cloned data object. - */ - function cloneData(data) { - var fn, - ctor, - result = data; - - if (isArray(data)) { - result = map(data, cloneData); - } - else if (data === Object(data)) { - ctor = data.constructor; - result = ctor == Object ? {} : (fn = function(){}, fn.prototype = ctor.prototype, new fn); - forOwn(data, function(value, key) { - result[key] = cloneData(value); - }); - } - return result; - } - - /** - * Creates a Browserscope results object. - * - * @private - * @returns {Object|Null} Browserscope results object or null. - */ - function createSnapshot() { - // clone benches, exclude those that are errored, unrun, or have hz of Infinity - var benches = invoke(filter(ui.benchmarks, 'successful'), 'clone'), - fastest = filter(benches, 'fastest'), - slowest = filter(benches, 'slowest'), - neither = filter(benches, function(bench) { - return indexOf(fastest, bench) + indexOf(slowest, bench) == -2; - }); - - function merge(destination, source) { - destination.count = source.count; - destination.cycles = source.cycles; - destination.hz = source.hz; - destination.stats = extend({}, source.stats); - } - - // normalize results on slowest in each category - each(fastest.concat(slowest), function(bench) { - merge(bench, indexOf(fastest, bench) > -1 ? fastest[fastest.length - 1] : slowest[0]); - }); - - // sort slowest to fastest - // (a larger `mean` indicates a slower benchmark) - neither.sort(function(a, b) { - a = a.stats; b = b.stats; - return (a.mean + a.moe > b.mean + b.moe) ? -1 : 1; - }); - - // normalize the leftover benchmarks - reduce(neither, function(prev, bench) { - // if the previous slower benchmark is indistinguishable from - // the current then use the previous benchmark's values - if (prev.compare(bench) == 0) { - merge(bench, prev); - } - return bench; - }); - - // append benchmark ids for duplicate names or names with no alphanumeric/space characters - // and use the upper limit of the confidence interval to compute a lower hz - // to avoid recording inflated results caused by a high margin or error - return reduce(benches, function(result, bench, key) { - var stats = bench.stats; - result || (result = {}); - key = toLabel(bench.name); - result[key && !hasKey(result, key) ? key : key + bench.id ] = floor(1 / (stats.mean + stats.moe)); - return result; - }, null); - } - - /** - * Retrieves the "cells" array from a given Google visualization data row object. - * - * @private - * @param {Object} object The data row object. - * @returns {Array} An array of cell objects. - */ - function getDataCells(object) { - // resolve cells by duck typing because of munged property names - var result = []; - forOwn(object, function(value) { - return !(isArray(value) && (result = value)); - }); - // remove empty entries which occur when not all the tests are recorded - return filter(result, Boolean); - } - - /** - * Retrieves the "labels" array from a given Google visualization data table object. - * - * @private - * @param {Object} object The data table object. - * @returns {Array} An array of label objects. - */ - function getDataLabels(object) { - var result = [], - labelMap = {}; - - // resolve labels by duck typing because of munged property names - forOwn(object, function(value) { - return !(isArray(value) && 0 in value && 'type' in value[0] && (result = value)); - }); - // create a data map of labels to names - each(ui.benchmarks, function(bench) { - var key = toLabel(bench.name); - labelMap[key && !hasKey(labelMap, key) ? key : key + bench.id ] = bench.name; - }); - // replace Browserscope's basic labels with benchmark names - return each(result, function(cell) { - var name = labelMap[cell.label]; - name && (cell.label = name); - }); - } - - /** - * Retrieves the "rows" array from a given Google visualization data table object. - * - * @private - * @param {Object} object The data table object. - * @returns {Array} An array of row objects. - */ - function getDataRows(object) { - var name, - filterBy = cache.lastFilterBy, - browserName = toBrowserName(getText(query('strong', '#bs-ua')[0]), filterBy), - uaClass = ui.browserscope.uaClass, - result = []; - - // resolve rows by duck typing because of munged property names - forOwn(object, function(value, key) { - return !(isArray(value) && 0 in value && !('type' in value[0]) && (name = key, result = value)); - }); - // remove empty rows and set the `p.className` on the browser - // name cell that matches the user's browser name - if (result.length) { - result = object[name] = filter(result, function(value) { - var cells = getDataCells(value), - first = cells[0], - second = cells[1]; - - // cells[0] is the browser name cell so instead we check cells[1] - // for the presence of ops/sec data to determine if a row is empty or not - if (first && second && second.f) { - delete first.p.className; - if (browserName == toBrowserName(first.f, filterBy)) { - first.p.className = uaClass; - } - return true; - } - }); - } - return result; - } - - /** - * Checks if a value has an internal [[Class]] of Array. - * - * @private - * @param {Mixed} value The value to check. - * @returns {Boolean} Returns `true` if the value has an internal [[Class]] of - * Array, else `false`. - */ - function isArray(value) { - return toString.call(value) == '[object Array]'; - } - - /** - * Executes a callback at a given delay interval until it returns `false`. - * - * @private - * @param {Function} callback The function called every poll interval. - * @param {Number} delay The delay between callback calls (secs). - */ - function poll(callback, delay) { - function poller(init) { - if (init || callback() !== false) { - setTimeout(poller, delay * 1e3); - } - } - poller(true); - } - - /** - * Cleans up the last action and sets the current action. - * - * @private - * @param {String} action The current action. - */ - function setAction(action) { - clearTimeout(cache.timers[cache.lastAction]); - cache.lastAction = action; - } - - /** - * Converts the browser name version number to the format allowed by the - * specified filter. - * - * @private - * @param {String} name The full browser name . - * @param {String} filterBy The filter formating rules to apply. - * @returns {String} The converted browser name. - */ - function toBrowserName(name, filterBy) { - name || (name = ''); - if (filterBy == 'all') { - // truncate something like 1.0.0 to 1 - name = name.replace(/(\d+)[.0]+$/, '$1'); - } - else if (filterBy == 'family') { - // truncate something like XYZ 1.2 to XYZ - name = name.replace(/[.\d\s]+$/, ''); - } - else if (/minor|popular/.test(filterBy) && /\d+(?:\.[1-9])+$/.test(name)) { - // truncate something like 1.2.3 to 1.2 - name = name.replace(/(\d+\.[1-9])(\.[.\d]+$)/, '$1'); - } - else { - // truncate something like 1.0 to 1 or 1.2.3 to 1 but leave something like 1.2 alone - name = name.replace(/(\d+)(?:(\.[1-9]$)|(\.[.\d]+$))/, '$1$2'); - } - return name; - } - - /** - * Replaces non-alphanumeric characters with spaces because Browserscope labels - * can only contain alphanumeric characters and spaces. - * - * @private - * @param {String} text The text to be converted. - * @returns {String} The Browserscope safe label text. - * @see http://code.google.com/p/browserscope/issues/detail?id=271 - */ - function toLabel(text) { - return (text || '').replace(/[^a-z0-9]+/gi, ' '); - } - - /*--------------------------------------------------------------------------*/ - - /** - * Loads Browserscope's cumulative results table. - * - * @static - * @memberOf ui.browserscope - * @param {Object} options The options object. - */ - function load(options) { - options || (options = {}); - - var fired, - me = ui.browserscope, - cont = me.container, - filterBy = cache.lastFilterBy = options.filterBy || cache.lastFilterBy, - responses = cache.responses, - response = cache.responses[filterBy], - visualization = window.google && google.visualization; - - function onComplete(response) { - var lastResponse = responses[filterBy]; - if (!fired) { - // set the fired flag to avoid Google's own timeout - fired = true; - // render if the filter is still the same, else cache the result - if (filterBy == cache.lastFilterBy) { - me.render({ 'force': true, 'response': lastResponse || response }); - } else if(!lastResponse && response && !response.isError()) { - responses[filterBy] = response; - } - } - } - - // set last action in case the load fails and a retry is needed - setAction('load'); - - // exit early if there is no container element or the response is cached - // and retry if the visualization library hasn't loaded yet - if (!cont || !visualization || !visualization.Query || response) { - cont && onComplete(response); - } - else if (!ui.running) { - // set our own load timeout to display an error message and retry loading - cache.timers.load = setTimeout(onComplete, me.timings.timeout * 1e3); - // set "loading" message and attempt to load Browserscope data - setMessage(me.texts.loading); - // request Browserscope pass chart data to `google.visualization.Query.setResponse()` - (new visualization.Query( - '//www.browserscope.org/gviz_table_data?category=usertest_' + me.key + '&v=' + filterMap[filterBy], - { 'sendMethod': 'scriptInjection' } - )) - .send(onComplete); - } - } - - /** - * Creates a Browserscope beacon and posts the benchmark results. - * - * @static - * @memberOf ui.browserscope - */ - function post() { - var idoc, - iframe, - body = document.body, - me = ui.browserscope, - key = me.key, - timings = me.timings, - name = 'browserscope-' + (cache.counter++) + '-' + (+new Date), - snapshot = createSnapshot(); - - // set last action in case the post fails and a retry is needed - setAction('post'); - - if (key && snapshot && me.postable && !ui.running && !/Simulator/i.test(Benchmark.platform)) { - // create new beacon - // (the name contains a timestamp so `cleanup()` can determine when to remove it) - iframe = createElement('iframe', name); - body.insertBefore(iframe, body.firstChild); - idoc = frames[name].document; - iframe.style.display = 'none'; - - // expose results snapshot - me.snapshot = snapshot; - // set "posting" message and attempt to post the results snapshot - setMessage(me.texts.post); - // Note: We originally created an iframe to avoid Browerscope's old limit - // of one beacon per page load. It's currently used to implement custom - // request timeout and retry routines. - idoc.write(interpolate( - // the doctype is required so Browserscope detects the correct IE compat mode - '#{doctype}<title></title><body><script>' + - 'with(parent.ui.browserscope){' + - 'var _bTestResults=snapshot,' + - '_bC=function(){clearTimeout(_bT);parent.setTimeout(function(){purge();load()},#{refresh}*1e3)},' + - '_bT=setTimeout(function(){_bC=function(){};render()},#{timeout}*1e3)' + - '}<\/script>' + - '<script src=//www.browserscope.org/user/beacon/#{key}?callback=_bC><\/script>', - { - 'doctype': /css/i.test(document.compatMode) ? '<!doctype html>' : '', - 'key': key, - 'refresh': timings.refresh, - 'timeout': timings.timeout - } - )); - // avoid the IE spinner of doom - // http://www.google.com/search?q=IE+throbber+of+doom - idoc.close(); - } - else { - me.load(); - } - } - - /** - * Purges the Browserscope response cache. - * - * @static - * @memberOf ui.browserscope - * @param {String} key The key of a single cache entry to clear. - */ - function purge(key) { - // we don't pave the cache object with a new one to preserve existing references - var responses = cache.responses; - if (key) { - delete responses[key]; - } else { - forOwn(responses, function(value, key) { - delete responses[key]; - }); - } - } - - /** - * Renders the cumulative results table. - * (tweak the dimensions and styles to best fit your environment) - * - * @static - * @memberOf ui.browserscope - * @param {Object} options The options object. - */ - function render(options) { - options || (options = {}); - - // coordinates, dimensions, and sizes are in px - var areaHeight, - cellWidth, - data, - labels, - rowCount, - rows, - me = ui.browserscope, - cont = me.container, - responses = cache.responses, - visualization = window.google && google.visualization, - lastChart = cache.lastChart, - chart = cache.lastChart = options.chart || lastChart, - lastFilterBy = cache.lastFilterBy, - filterBy = cache.lastFilterBy = options.filterBy || lastFilterBy, - lastResponse = responses[filterBy], - response = responses[filterBy] = 'response' in options ? (response = options.response) && !response.isError() && response : lastResponse, - areaWidth = '100%', - cellHeight = 80, - fontSize = 13, - height = 'auto', - hTitle = 'operations per second (higher is better)', - hTitleHeight = 48, - left = 240, - legend = 'top', - maxChars = 0, - maxCharsLimit = 20, - maxOps = 0, - minHeight = 480, - minWidth = cont && cont.offsetWidth || 948, - title = '', - top = 50, - vTitle = '', - vTitleWidth = 48, - width = minWidth; - - function retry(force) { - var action = cache.lastAction; - if (force || ui.running) { - cache.timers[action] = setTimeout(retry, me.timings.retry * 1e3); - } else { - me[action].apply(me, action == 'render' ? [options] : []); - } - } - - // set action to clear any timeouts and prep for retries - setAction(response ? 'render' : cache.lastAction); - - // exit early if there is no container element, the data filter has changed or nothing has changed - if (!cont || visualization && (filterBy != lastFilterBy || - (!options.force && chart == lastChart && response == lastResponse))) { - cont && filterBy != lastFilterBy && load(options); - } - // retry if response data is empty/errored or the visualization library hasn't loaded yet - else if (!response || !visualization) { - // set error message for empty/errored response - !response && visualization && setMessage(me.texts.error); - retry(true); - } - // visualization chart gallary - // http://code.google.com/apis/chart/interactive/docs/gallery.html - else if (!ui.running) { - cont.className = ''; - data = cloneData(response.getDataTable()); - labels = getDataLabels(data); - rows = getDataRows(data); - rowCount = rows.length; - chart = chart.charAt(0).toUpperCase() + chart.slice(1).toLowerCase(); - - // adjust data for non-tabular displays - if (chart != 'Table') { - // remove "# Tests" run count label (without label data the row will be ignored) - labels.pop(); - - // modify row data - each(rows, function(row) { - each(getDataCells(row), function(cell, index, cells) { - var lastIndex = cells.length - 1; - - // cells[1] through cells[lastIndex - 1] are ops/sec cells - if (/^[\d.,]+$/.test(cell.f)) { - // assign ops/sec as cell value - cell.v = +cell.f.replace(/,/g, ''); - // add rate to the text - cell.f += ' ops/sec'; - // capture highest ops value to use when computing the left coordinate - maxOps = max(maxOps, cell.v); - } - // cells[0] is the browser name cell - // cells[lastIndex] is the run count cell and has no `f` property - else if (cell.f) { - // add test run count to browser name - cell.f += chart == 'Pie' ? '' : ' (' + (cells[lastIndex].v || 1) + ')'; - // capture longest char count to use when computing left coordinate/cell width - maxChars = min(maxCharsLimit, max(maxChars, cell.f.length)); - } - // compute sum of all ops/sec for pie charts - if (chart == 'Pie') { - if (index == lastIndex) { - cells[1].f = formatNumber(cells[1].v) + ' total ops/sec'; - } else if (index > 1 && typeof cell.v == 'number') { - cells[1].v += cell.v; - } - } - // if the browser name matches the user's browser then style it - if (cell.p && cell.p.className) { - // prefix the browser name with a line separator (\u2028) because it's not rendered - // (IE may render a negligible space in the tooltip of browser names truncated with ellipsis) - cell.f = uaToken + cell.f; - // poll until the chart elements exist and are styled - poll(function() { return !addChartStyle(); }, 0.01); - } - }); - }); - - // adjust captions and chart dimensions - if (chart == 'Bar') { - // use minHeight to avoid sizing issues when there is only 1 bar - height = max(minHeight, top + (rowCount * cellHeight)); - // compute left by adding the longest approximate vAxis text width and - // a right pad of 10px - left = (maxChars * (fontSize / 1.6)) + 10; - // get percentage of width left after subtracting the chart's left - // coordinate and room for the ops/sec number - areaWidth = (100 - (((left + 50) / width) * 100)) + '%'; - } - else { - // swap captions (the browser list caption is blank to conserve space) - vTitle = [hTitle, hTitle = vTitle][0]; - height = minHeight; - - if (chart == 'Pie') { - legend = 'right'; - title = 'Total operations per second by browser (higher is better)'; - } - else { - hTitleHeight = 28; - // compute left by getting the sum of the horizontal space wanted - // for the vAxis title's width, the approximate vAxis text width, and - // the 13px gap between the chart and the right side of the vAxis text - left = vTitleWidth + (formatNumber(maxOps).length * (fontSize / 1.6)) + 13; - // compute cell width by adding the longest approximate hAxis text - // width and wiggle room of 26px - cellWidth = (maxChars * (fontSize / 2)) + 26; - // use minWidth to avoid clipping the key - width = max(minWidth, left + (rowCount * cellWidth)); - } - } - // get percentage of height left after subtracting the vertical space wanted - // for the hAxis title's height, text size, the chart's top coordinate, - // and the 8px gap between the chart and the top of the hAxis text - areaHeight = (100 - (((hTitleHeight + fontSize + top + 8) / height) * 100)) + '%'; - // make chart type recognizable - chart += 'Chart'; - } - - if (rowCount && visualization[chart]) { - new visualization[chart](cont).draw(data, { - 'colors': ui.browserscope.colors, - 'fontSize': fontSize, - 'is3D': true, - 'legend': legend, - 'height': height, - 'title': title, - 'width': width, - 'chartArea': { 'height': areaHeight, 'left': left, 'top': top, 'width': areaWidth }, - 'hAxis': { 'baseline': 0, 'title': hTitle }, - 'vAxis': { 'baseline': 0, 'title': vTitle } - }); - } else { - setMessage(me.texts.empty); - } - } - } - - /*--------------------------------------------------------------------------*/ - - // expose - ui.browserscope = { - - /** - * Your Browserscope API key. - * - * @memberOf ui.browserscope - * @type String - */ - 'key': '', - - /** - * A flag to indicate if posting is enabled or disabled. - * - * @memberOf ui.browserscope - * @type Boolean - */ - 'postable': true, - - /** - * The selector of the element to contain the entire Browserscope UI. - * - * @memberOf ui.browserscope - * @type String - */ - 'selector': '', - - /** - * The class name used to style the user's browser name when it appears - * in charts. - * - * @memberOf ui.browserscope - * @type String - */ - 'uaClass': 'rt-ua-cur', - - /** - * Object containing various timings settings. - * - * @memberOf ui.browserscope - * @type Object - */ - 'timings': { - - /** - * The delay between removing abandoned script and iframe elements (secs). - * - * @memberOf ui.browserscope.timings - * @type Number - */ - 'cleanup': 10, - - /** - * The delay before refreshing the cumulative results after posting (secs). - * - * @memberOf ui.browserscope.timings - * @type Number - */ - 'refresh': 3, - - /** - * The delay between load attempts (secs). - * - * @memberOf ui.browserscope.timings - * @type Number - */ - 'retry': 5, - - /** - * The time to wait for a request to finish (secs). - * - * @memberOf ui.browserscope.timings - * @type Number - */ - 'timeout': 10 - }, - - /** - * Object containing various text messages. - * - * @memberOf ui.browserscope - * @type Object - */ - 'texts': { - - /** - * The text shown when their is no recorded data available to report. - * - * @memberOf ui.browserscope.texts - * @type String - */ - 'empty': 'No data available', - - /** - * The text shown when the cumulative results data cannot be retrieved. - * - * @memberOf ui.browserscope.texts - * @type String - */ - 'error': 'The get/post request has failed :(', - - /** - * The text shown while waiting for the cumulative results data to load. - * - * @memberOf ui.browserscope.texts - * @type String - */ - 'loading': 'Loading cumulative results data…', - - /** - * The text shown while posting the results snapshot to Browserscope. - * - * @memberOf ui.browserscope.texts - * @type String - */ - 'post': 'Posting results snapshot…', - - /** - * The text shown while benchmarks are running. - * - * @memberOf ui.browserscope.texts - * @type String - */ - 'wait': 'Benchmarks running. Please wait…' - }, - - // loads cumulative results table - 'load': load, - - // posts benchmark snapshot to Browserscope - 'post': post, - - // purges the Browserscope response cache - 'purge': purge, - - // renders cumulative results table - 'render': render - }; - - /*--------------------------------------------------------------------------*/ - - addListener(window, 'load', function() { - var me = ui.browserscope, - key = me.key, - placeholder = key && query(me.selector)[0]; - - // create results html - if (placeholder) { - setHTML(placeholder, - '<h1 id=bs-logo><a href=//www.browserscope.org/user/tests/table/#{key}>' + - '<span>Browserscope</span></a></h1>' + - '<div class=bs-rt><div id=bs-chart></div></div>', - { 'key': key }); - - // the element the charts are inserted into - me.container = query('#bs-chart')[0]; - - // Browserscope's UA div is inserted before an element with the id of "bs-ua-script" - loadScript('//www.browserscope.org/ua?o=js', me.container).id = 'bs-ua-script'; - - // the "autoload" string can be created with - // http://code.google.com/apis/loader/autoloader-wizard.html - loadScript('//www.google.com/jsapi?autoload=' + encodeURIComponent('{' + - 'modules:[{' + - 'name:"visualization",' + - 'version:1,' + - 'packages:["corechart","table"],' + - 'callback:ui.browserscope.load' + - '}]' + - '}')); - - // init garbage collector - cleanup(); - } - }); - - // hide the chart while benchmarks are running - ui.on('start', function() { - setMessage(ui.browserscope.texts.wait); - }) - .on('abort', function() { - ui.browserscope.render({ 'force': true }); - }); - -}(this, document)); |