aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/vendor/benchmark/plugin/ui.browserscope.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/vendor/benchmark/plugin/ui.browserscope.js')
-rw-r--r--web/src/vendor/benchmark/plugin/ui.browserscope.js1052
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&hellip;',
-
- /**
- * The text shown while posting the results snapshot to Browserscope.
- *
- * @memberOf ui.browserscope.texts
- * @type String
- */
- 'post': 'Posting results snapshot&hellip;',
-
- /**
- * The text shown while benchmarks are running.
- *
- * @memberOf ui.browserscope.texts
- * @type String
- */
- 'wait': 'Benchmarks running. Please wait&hellip;'
- },
-
- // 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));