<commit_before>/**
* @fileoverview client模式专用，根据map.json和static-conf.js合并资源
* @author  liweitao
*/

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var vinylFs = require('vinyl-fs');
var es = require('event-stream');
var gutil = require('gulp-util');

var Util = require('../../util');

var concatCore = require('./athena_concat_core');

var exludeResource = {
  js: [],
  css: []
};

function getWidgetPath (modulePath, widget, config) {
  return path.join(modulePath, config.dest, '_', 'widget', widget);
}

function resourcesConcat (opts) {
  var config = _.assign({
    cwd: undefined,
    module: undefined,
    pageFiles: [],
    map: 'map.json',
    dest: 'dist',
    end: function () {}
  }, opts);

  if (!config.cwd || !config.module) {
    gutil.log(gutil.colors.red('传入参数有误 at concat!'));
    return;
  }
  var modulePath = path.join(config.cwd, config.module);
  var exludeResourcePath = path.join(modulePath, 'dist', '_exlude_resource.json');
  exludeResource = Util.readJsonFile(exludeResourcePath);
  var streamArr = [];
  concactStatic(modulePath, config, function () {
    fs.readFile(path.join(modulePath, config.map), function (err, data) {
      if (err) {
        gutil.log(gutil.colors.red(config.map + '文件读取错误！'));
        if (_.isFunction(config.end)) {
          config.end();
        }
        return;
      }
      if (config.pageFiles.length > 0) {
        config.pageFiles = config.pageFiles.map(function (item) {
          return path.basename(item);
        });
      }
      var fileContent = String(data);
      var conf = JSON.parse(fileContent).dependency;
      if (_.isEmpty(conf)) {
        if (_.isFunction(config.end)) {
          config.end();
        }
        return;
      }
      for (var key in conf) {
        if (config.pageFiles.length && config.pageFiles.indexOf(key) < 0) {
          continue;
        }
        if (conf.hasOwnProperty(key)) {
          var page = key.split('.')[0];
          var pageConf = conf[key];
          var cssFiles = [];
          var jsFiles = [];
          var pagePath = path.join(modulePath, config.dest, '_', 'page', page);
          var appConf = require(path.join(config.cwd, 'app-conf'));
          pageConf.forEach(function (widgetItem) {
            if (widgetItem.module === appConf.common) {
              var mp = path.join(config.cwd, widgetItem.module);
              var widgetPath = getWidgetPath(mp, widgetItem.widgetName, config);
              cssFiles.push(path.join(widgetPath, '**', '*.css'));
              jsFiles.push(path.join(widgetPath, '**', '*.js'));
            }
          });
          pageConf.forEach(function (widgetItem) {
            if (widgetItem.module !== appConf.common) {
              var mp = path.join(config.cwd, widgetItem.module);
              var widgetPath = getWidgetPath(mp, widgetItem.widgetName, config);
              cssFiles.push(path.join(widgetPath, '**', '*.css'));
              jsFiles.push(path.join(widgetPath, '**', '*.js'));
            }
          });
          cssFiles.push(path.join(pagePath, '**', '*.css'));
          cssFiles = cssFiles.concat(exludeResource.css.map(function (item) {
            return path.join('!' + config.cwd, item.module, config.dest, '_', item.file);
          }));
          jsFiles.push(path.join(pagePath, '**', '*.js'));
          jsFiles = jsFiles.concat(exludeResource.js.map(function (item) {
            return path.join('!' + config.cwd, item.module, config.dest, '_', item.file);
          }));
          streamArr.push(es.merge(
            vinylFs
              .src(cssFiles)
              .pipe(concatCore(page + '.css'))
              .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'css'))),
            vinylFs
              .src(jsFiles)
              .pipe(concatCore(page + '.js'))
              .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'js')))
          ));
        }
      }
      es.merge(streamArr).on('end', function () {
        if (_.isFunction(opts.end)) {
          opts.end();
        }
      });
    });
  });
}

// 通过读取static-conf配置来进行资源合并
function concactStatic (modulePath, config, cb) {
  var streamArr = [];
  var staticPath = require(path.join(modulePath, 'static-conf')).staticPath;
  streamArr.push(vinylFs
    .src([path.join(modulePath, config.dest, '_', 'static', '**', '*.css'), path.join(modulePath, config.dest, '_', 'static', 'sass', '**', '*.css')])
    .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static')))
  );
  streamArr.push(vinylFs
    .src(path.join(modulePath, config.dest, '_', 'static', '**', '*.js'))
    .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static')))
  );
  es.merge(streamArr).on('end', function () {
    var streamArr = [];
    if (_.isEmpty(staticPath)) {
      cb();
      return;
    }
    for (var key in staticPath) {
      // css
      if (path.extname(key).indexOf('css') >= 0) {
        streamArr.push(vinylFs
          .src(staticPath[key].map(function (item) {
            return path.join(modulePath, config.dest, '_', item);
          }))
          .pipe(concatCore(key))
          .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'css'))));
      }

      // js
      if (path.extname(key).indexOf('js') >= 0) {
        streamArr.push(vinylFs
          .src(staticPath[key].map(function (item) {
            return path.join(modulePath, config.dest, '_', item);
          }))
          .pipe(concatCore(key))
          .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'js'))));
      }
    }
    es.merge(streamArr).on('end', function () {
      cb();
    });
  });
}

module.exports = resourcesConcat;
<commit_msg>update:编译时扫描代码检查页面引用组件是否在引用的公共模块页面中被引用，避免重复引用资源<commit_after>/**
* @fileoverview client模式专用，根据map.json和static-conf.js合并资源
* @author  liweitao
*/

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var vinylFs = require('vinyl-fs');
var es = require('event-stream');
var gutil = require('gulp-util');

var Util = require('../../util');

var concatCore = require('./athena_concat_core');

var exludeResource = {
  js: [],
  css: []
};

function getWidgetPath (modulePath, widget, config) {
  return path.join(modulePath, config.dest, '_', 'widget', widget);
}

function resourcesConcat (opts) {
  var config = _.assign({
    cwd: undefined,
    module: undefined,
    pageFiles: [],
    map: 'map.json',
    dest: 'dist',
    end: function () {}
  }, opts);

  if (!config.cwd || !config.module) {
    gutil.log(gutil.colors.red('传入参数有误 at concat!'));
    return;
  }
  var modulePath = path.join(config.cwd, config.module);
  var exludeResourcePath = path.join(modulePath, config.dest, '_exlude_resource.json');
  exludeResource = Util.readJsonFile(exludeResourcePath);
  var streamArr = [];
  var appConf = require(path.join(config.cwd, 'app-conf'));
  var commonMapJson = Util.readJsonFile(path.join(config.cwd, appConf.common, config.map));

  concactStatic(modulePath, config, function () {
    fs.readFile(path.join(modulePath, config.map), function (err, data) {
      if (err) {
        gutil.log(gutil.colors.red(config.map + '文件读取错误！'));
        if (_.isFunction(config.end)) {
          config.end();
        }
        return;
      }
      if (config.pageFiles.length > 0) {
        config.pageFiles = config.pageFiles.map(function (item) {
          return path.basename(item);
        });
      }
      var fileContent = String(data);
      var conf = JSON.parse(fileContent).dependency;
      if (_.isEmpty(conf)) {
        if (_.isFunction(config.end)) {
          config.end();
        }
        return;
      }
      for (var key in conf) {
        if (config.pageFiles.length && config.pageFiles.indexOf(key) < 0) {
          continue;
        }
        if (conf.hasOwnProperty(key)) {
          var page = key.split('.')[0];
          var pageConf = conf[key];
          var cssFiles = [];
          var jsFiles = [];
          var pagePath = path.join(modulePath, config.dest, '_', 'page', page);
          var include = JSON.parse(fileContent).include[key];
          var cssInclude = include.css;
          var jsInclude = include.js;
          var includeCommonWidgets = [];
          cssInclude.forEach(function (item) {
            if (item.module === appConf.common) {
              var css = item.name;
              var page = path.basename(css, path.extname(css)) + '.html';
              var cssDependency = commonMapJson['dependency'][page];
              if (cssDependency) {
                cssDependency.forEach(function (widgetItem) {
                  if (includeCommonWidgets.indexOf(widgetItem.widgetName) < 0) {
                    includeCommonWidgets.push(widgetItem.widgetName);
                  }
                });
              }
            }
          });
          jsInclude.forEach(function (item) {
            if (item.module === appConf.common) {
              var js = item.name;
              var page = path.basename(js, path.extname(js)) + '.html';
              var jsDependency = commonMapJson['dependency'][page];
              if (jsDependency) {
                jsDependency.forEach(function (widgetItem) {
                  if (includeCommonWidgets.indexOf(widgetItem.widgetName) < 0) {
                    includeCommonWidgets.push(widgetItem.widgetName);
                  }
                });
              }
            }
          });
          if (config.module === appConf.common) {
            includeCommonWidgets = [];
          }
          console.log(includeCommonWidgets);
          pageConf.forEach(function (widgetItem) {
            if (widgetItem.module === appConf.common && includeCommonWidgets.indexOf(widgetItem.widgetName) < 0) {
              var mp = path.join(config.cwd, widgetItem.module);
              var widgetPath = getWidgetPath(mp, widgetItem.widgetName, config);
              cssFiles.push(path.join(widgetPath, '**', '*.css'));
              jsFiles.push(path.join(widgetPath, '**', '*.js'));
            }
          });
          pageConf.forEach(function (widgetItem) {
            if (widgetItem.module !== appConf.common) {
              var mp = path.join(config.cwd, widgetItem.module);
              var widgetPath = getWidgetPath(mp, widgetItem.widgetName, config);
              cssFiles.push(path.join(widgetPath, '**', '*.css'));
              jsFiles.push(path.join(widgetPath, '**', '*.js'));
            }
          });
          cssFiles.push(path.join(pagePath, '**', '*.css'));
          cssFiles = cssFiles.concat(exludeResource.css.map(function (item) {
            return path.join('!' + config.cwd, item.module, config.dest, '_', item.file);
          }));
          jsFiles.push(path.join(pagePath, '**', '*.js'));
          jsFiles = jsFiles.concat(exludeResource.js.map(function (item) {
            return path.join('!' + config.cwd, item.module, config.dest, '_', item.file);
          }));
          streamArr.push(es.merge(
            vinylFs
              .src(cssFiles)
              .pipe(concatCore(page + '.css'))
              .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'css'))),
            vinylFs
              .src(jsFiles)
              .pipe(concatCore(page + '.js'))
              .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'js')))
          ));
        }
      }
      es.merge(streamArr).on('end', function () {
        if (_.isFunction(opts.end)) {
          opts.end();
        }
      });
    });
  });
}

// 通过读取static-conf配置来进行资源合并
function concactStatic (modulePath, config, cb) {
  var streamArr = [];
  var staticPath = require(path.join(modulePath, 'static-conf')).staticPath;
  streamArr.push(vinylFs
    .src([path.join(modulePath, config.dest, '_', 'static', '**', '*.css'), path.join(modulePath, config.dest, '_', 'static', 'sass', '**', '*.css')])
    .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static')))
  );
  streamArr.push(vinylFs
    .src(path.join(modulePath, config.dest, '_', 'static', '**', '*.js'))
    .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static')))
  );
  es.merge(streamArr).on('end', function () {
    var streamArr = [];
    if (_.isEmpty(staticPath)) {
      cb();
      return;
    }
    for (var key in staticPath) {
      // css
      if (path.extname(key).indexOf('css') >= 0) {
        streamArr.push(vinylFs
          .src(staticPath[key].map(function (item) {
            return path.join(modulePath, config.dest, '_', item);
          }))
          .pipe(concatCore(key))
          .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'css'))));
      }

      // js
      if (path.extname(key).indexOf('js') >= 0) {
        streamArr.push(vinylFs
          .src(staticPath[key].map(function (item) {
            return path.join(modulePath, config.dest, '_', item);
          }))
          .pipe(concatCore(key))
          .pipe(vinylFs.dest(path.join(modulePath, config.dest, '_static', 'js'))));
      }
    }
    es.merge(streamArr).on('end', function () {
      cb();
    });
  });
}

module.exports = resourcesConcat;
<|endoftext|>


<commit_before>'use strict';

const log = require('intel').getLogger('browsertime.chrome');
const { promisify } = require('util');
const { Type } = require('selenium-webdriver').logging;
const harBuilder = require('../../support/har/');
const perflogParser = require('chrome-har');
const fs = require('fs');
const { parseCpuTrace } = require('../cpu');
const webdriver = require('selenium-webdriver');
const zlib = require('zlib');
const traceCategoriesParser = require('../traceCategoriesParser');
const pathToFolder = require('../../support/pathToFolder');
const path = require('path');

const unlink = promisify(fs.unlink);

const { createAndroidConnection } = require('../../android');

const CHROME_NAME_AND_VERSION_JS = `return (function() {
  var match = navigator.userAgent.match(/(Chrom(e|ium))\\/(([0-9]+\\.?)*)/);

  if (match)
    return {
      'name': match[1],
      'version': match[3]
    };
  else
    return {};
})();`;

class ChromeDelegate {
  constructor(storageManager, options) {
    this.options = options;
    this.chrome = options.chrome || {};
    this.skipHar = options.skipHar || false;
    this.logPerfEntries = !!this.chrome.collectPerfLog;
    this.collectTracingEvents =
      this.chrome.traceCategories || this.chrome.timeline;
    this.baseDir = storageManager.directory;
    this.storageManeger = storageManager;
    // We keep track of all alias and URLs
    this.aliasAndUrl = {};
  }

  async onStart() {
    this.hars = [];
  }

  async onStartIteration(runner) {
    // enable getting extra performance metrics
    if (this.chrome.cdp && this.chrome.cdp.performance === true) {
      await runner.sendDevToolsCommand('Performance.enable');
    }

    // Make sure we clear the console log
    // Hopefully one time is enough?
    await runner.getLogs(Type.BROWSER);

    // remove irrelevant entries from performance log
    // and since Chromedriver 2.29 there's a bug
    // https://bugs.chromium.org/p/chromedriver/issues/detail?id=1811
    // that can be fixed by emptying the logs twice :|
    await runner.getLogs(Type.PERFORMANCE);
    await runner.getLogs(Type.PERFORMANCE);

    if (this.skipHar) {
      return;
    }
  }

  async clear(runner) {
    await runner.getLogs(Type.PERFORMANCE);
    await runner.getLogs(Type.PERFORMANCE);
  }

  async onStopIteration() {}

  async onCollect(runner, index, result) {
    if (this.chrome.collectNetLog && !this.chrome.android) {
      const gzip = zlib.createGzip();
      const netlog = `${this.baseDir}/chromeNetlog.json`;
      const input = fs.createReadStream(netlog);
      const out = fs.createWriteStream(
        path.join(
          this.baseDir,
          pathToFolder(result.url, this.options),
          `chromeNetlog-${index}.json.gz`
        )
      );
      out.on('finish', function() {
        return unlink(netlog);
      });
      input.pipe(gzip).pipe(out);
    }

    if (this.chrome.collectConsoleLog) {
      result.extraJson[`console-${index}.json`] = await runner.getLogs(
        webdriver.logging.Type.BROWSER
      );
    }

    const rawCDPMetrics = await runner.sendAndGetDevToolsCommand(
      'Performance.getMetrics'
    );

    const cleanedMetrics = {};
    for (let m of rawCDPMetrics.metrics) {
      if (
        m.name === 'FirstMeaningfulPaint' ||
        m.name === 'DomContentLoaded' ||
        m.name === 'Timestamp' ||
        m.name === 'NavigationStart'
      ) {
        // skip
      } else {
        cleanedMetrics[m.name] = m.value;
      }
    }

    result.cdp = { performance: cleanedMetrics };

    if (this.chrome.collectNetLog && this.chrome.android) {
      const android = createAndroidConnection(this.options);
      await android.initConnection();
      // THIS needs to be unique per page
      await android.pullNetLog(
        path.join(
          this.baseDir,
          pathToFolder(result.url, this.options),
          `chromeNetlog-${index}.json.gz`
        )
      );
    }

    if (this.skipHar) {
      return;
    }

    log.debug('Getting performance logs from Chrome');

    const logs = await runner.getLogs(Type.PERFORMANCE);
    const messages = logs.map(entry => JSON.parse(entry.message).message);

    if (this.logPerfEntries) {
      result.extraJson[`chromePerflog-${index}.json`] = messages;
    }
    if (this.collectTracingEvents) {
      const trace = traceCategoriesParser.parse(messages);
      result.extraJson[`trace-${index}.json`] = trace;
      const cpu = await parseCpuTrace(trace);
      result.cpu = cpu;
    }
    // CLEANUP since Chromedriver 2.29 there's a bug
    // https://bugs.chromium.org/p/chromedriver/issues/detail?id=1811
    await runner.getLogs(Type.PERFORMANCE);

    const har = perflogParser.harFromMessages(messages);
    const info = await runner.runScript(
      CHROME_NAME_AND_VERSION_JS,
      'CHROME_NAME_AND_VERSION_JS'
    );
    if (this.chrome.mobileEmulation) {
      info.name = `Chrome Emulated ${this.chrome.mobileEmulation.deviceName}`;
    }
    harBuilder.addBrowser(har, info.name, info.version);

    if (har.log.pages.length > 0) {
      har.log.pages[0].title = `${result.url} run ${index}`;
      // Hack to add the URL from a SPA
      if (result.alias && !this.aliasAndUrl[result.alias]) {
        this.aliasAndUrl[result.alias] = result.url;
        har.log.pages[0]._url = result.url;
      } else if (result.alias && this.aliasAndUrl[result.alias]) {
        har.log.pages[0]._url = this.aliasAndUrl[result.alias];
      } else {
        har.log.pages[0]._url = result.url;
      }
    }

    this.hars.push(har);
  }

  async onStop() {
    if (!this.skipHar) {
      return { har: harBuilder.mergeHars(this.hars) };
    } else return {};
  }
}

module.exports = ChromeDelegate;
<commit_msg>Report duration metrics in ms. (#809)<commit_after>'use strict';

const log = require('intel').getLogger('browsertime.chrome');
const { promisify } = require('util');
const { Type } = require('selenium-webdriver').logging;
const harBuilder = require('../../support/har/');
const perflogParser = require('chrome-har');
const fs = require('fs');
const { parseCpuTrace } = require('../cpu');
const webdriver = require('selenium-webdriver');
const zlib = require('zlib');
const traceCategoriesParser = require('../traceCategoriesParser');
const pathToFolder = require('../../support/pathToFolder');
const path = require('path');

const unlink = promisify(fs.unlink);

const { createAndroidConnection } = require('../../android');

const CHROME_NAME_AND_VERSION_JS = `return (function() {
  var match = navigator.userAgent.match(/(Chrom(e|ium))\\/(([0-9]+\\.?)*)/);

  if (match)
    return {
      'name': match[1],
      'version': match[3]
    };
  else
    return {};
})();`;

class ChromeDelegate {
  constructor(storageManager, options) {
    this.options = options;
    this.chrome = options.chrome || {};
    this.skipHar = options.skipHar || false;
    this.logPerfEntries = !!this.chrome.collectPerfLog;
    this.collectTracingEvents =
      this.chrome.traceCategories || this.chrome.timeline;
    this.baseDir = storageManager.directory;
    this.storageManeger = storageManager;
    // We keep track of all alias and URLs
    this.aliasAndUrl = {};
  }

  async onStart() {
    this.hars = [];
  }

  async onStartIteration(runner) {
    // enable getting extra performance metrics
    if (this.chrome.cdp && this.chrome.cdp.performance === true) {
      await runner.sendDevToolsCommand('Performance.enable');
    }

    // Make sure we clear the console log
    // Hopefully one time is enough?
    await runner.getLogs(Type.BROWSER);

    // remove irrelevant entries from performance log
    // and since Chromedriver 2.29 there's a bug
    // https://bugs.chromium.org/p/chromedriver/issues/detail?id=1811
    // that can be fixed by emptying the logs twice :|
    await runner.getLogs(Type.PERFORMANCE);
    await runner.getLogs(Type.PERFORMANCE);

    if (this.skipHar) {
      return;
    }
  }

  async clear(runner) {
    await runner.getLogs(Type.PERFORMANCE);
    await runner.getLogs(Type.PERFORMANCE);
  }

  async onStopIteration() {}

  async onCollect(runner, index, result) {
    if (this.chrome.collectNetLog && !this.chrome.android) {
      const gzip = zlib.createGzip();
      const netlog = `${this.baseDir}/chromeNetlog.json`;
      const input = fs.createReadStream(netlog);
      const out = fs.createWriteStream(
        path.join(
          this.baseDir,
          pathToFolder(result.url, this.options),
          `chromeNetlog-${index}.json.gz`
        )
      );
      out.on('finish', function() {
        return unlink(netlog);
      });
      input.pipe(gzip).pipe(out);
    }

    if (this.chrome.collectConsoleLog) {
      result.extraJson[`console-${index}.json`] = await runner.getLogs(
        webdriver.logging.Type.BROWSER
      );
    }

    const rawCDPMetrics = await runner.sendAndGetDevToolsCommand(
      'Performance.getMetrics'
    );

    const cleanedMetrics = {};
    for (let m of rawCDPMetrics.metrics) {
      if (
        m.name === 'FirstMeaningfulPaint' ||
        m.name === 'DomContentLoaded' ||
        m.name === 'Timestamp' ||
        m.name === 'NavigationStart'
      ) {
        // skip
      } else {
        if (m.name.indexOf('Duration') > -1) {
          cleanedMetrics[m.name] = m.value * 1000;
        } else {
          cleanedMetrics[m.name] = m.value;
        }
      }
    }

    result.cdp = { performance: cleanedMetrics };

    if (this.chrome.collectNetLog && this.chrome.android) {
      const android = createAndroidConnection(this.options);
      await android.initConnection();
      // THIS needs to be unique per page
      await android.pullNetLog(
        path.join(
          this.baseDir,
          pathToFolder(result.url, this.options),
          `chromeNetlog-${index}.json.gz`
        )
      );
    }

    if (this.skipHar) {
      return;
    }

    log.debug('Getting performance logs from Chrome');

    const logs = await runner.getLogs(Type.PERFORMANCE);
    const messages = logs.map(entry => JSON.parse(entry.message).message);

    if (this.logPerfEntries) {
      result.extraJson[`chromePerflog-${index}.json`] = messages;
    }
    if (this.collectTracingEvents) {
      const trace = traceCategoriesParser.parse(messages);
      result.extraJson[`trace-${index}.json`] = trace;
      const cpu = await parseCpuTrace(trace);
      result.cpu = cpu;
    }
    // CLEANUP since Chromedriver 2.29 there's a bug
    // https://bugs.chromium.org/p/chromedriver/issues/detail?id=1811
    await runner.getLogs(Type.PERFORMANCE);

    const har = perflogParser.harFromMessages(messages);
    const info = await runner.runScript(
      CHROME_NAME_AND_VERSION_JS,
      'CHROME_NAME_AND_VERSION_JS'
    );
    if (this.chrome.mobileEmulation) {
      info.name = `Chrome Emulated ${this.chrome.mobileEmulation.deviceName}`;
    }
    harBuilder.addBrowser(har, info.name, info.version);

    if (har.log.pages.length > 0) {
      har.log.pages[0].title = `${result.url} run ${index}`;
      // Hack to add the URL from a SPA
      if (result.alias && !this.aliasAndUrl[result.alias]) {
        this.aliasAndUrl[result.alias] = result.url;
        har.log.pages[0]._url = result.url;
      } else if (result.alias && this.aliasAndUrl[result.alias]) {
        har.log.pages[0]._url = this.aliasAndUrl[result.alias];
      } else {
        har.log.pages[0]._url = result.url;
      }
    }

    this.hars.push(har);
  }

  async onStop() {
    if (!this.skipHar) {
      return { har: harBuilder.mergeHars(this.hars) };
    } else return {};
  }
}

module.exports = ChromeDelegate;
<|endoftext|>


<commit_before>/**
 * Interaction for the analytics module
 */
/* global Highcharts */
jsBackend.analytics = {
  $chartPieChart: $('#chartPieChart'),
  $chartDoubleMetricPerDay: $('#chartDoubleMetricPerDay')
}

jsBackend.analytics.charts = {
  init: function () {
    if (jsBackend.analytics.$chartPieChart.length > 0 || jsBackend.analytics.$chartDoubleMetricPerDay.length > 0) {
      Highcharts.setOptions({
        colors: ['#2f77d1', '#021b45', '#ED561B', '#EDEF00', '#24CBE5', '#64E572', '#FF9655'],
        title: {text: ''},
        legend: {
          layout: 'vertical',
          borderWidth: 0,
          shadow: false,
          symbolPadding: 12,
          symbolWidth: 10,
          itemStyle: {cursor: 'pointer', color: '#000', lineHeight: '18px'},
          itemHoverStyle: {color: '#666'}
        }
      })
    }
  }
}

jsBackend.analytics.chartPieChart = {
  chart: '',

  init: function () {
    if (jsBackend.analytics.$chartPieChart.length > 0) { jsBackend.analytics.chartPieChart.create() }
  },

  // add new chart
  create: function () {
    // variables
    var $pieChartValues = $('#dataChartPieChart ul.data li')
    var pieChartData = []

    $pieChartValues.each(function () {
      // variables
      var $this = $(this)

      pieChartData.push({
        name: $this.children('span.label').html(),
        y: parseInt($this.children('span.value').html()),
        percentage: parseInt($this.children('span.percentage').html())
      })
    })

    var containerWidth = jsBackend.analytics.$chartPieChart.width()

    jsBackend.analytics.chartPieChart.chart = new Highcharts.Chart({
      chart: {
        renderTo: 'chartPieChart',
        height: 200,
        width: containerWidth,
        margin: [0, 160, 0, 0],
        backgroundColor: 'transparent'
      },
      credits: {enabled: false},
      plotArea: {shadow: null, borderWidth: null, backgroundColor: null},
      tooltip: {
        formatter: function () {
          var percentage = String(this.point.percentage)
          return '' + this.point.name + ': ' + this.y + ' (' + percentage.substring(0, $.inArray('.', percentage) + 3) + '%)'
        },
        borderWidth: 2,
        shadow: false
      },
      plotOptions: {
        pie: {
          allowPointSelect: true,
          dataLabels: {
            enabled: false
          },
          showInLegend: true
        }
      },
      legend: {align: 'right'},
      series: [{type: 'pie', data: pieChartData}]
    })
  },

  // destroy chart
  destroy: function () {
    jsBackend.analytics.chartPieChart.chart.destroy()
  }
}

jsBackend.analytics.chartDoubleMetricPerDay = {
  chart: '',

  init: function () {
    if (jsBackend.analytics.$chartDoubleMetricPerDay.length > 0) { jsBackend.analytics.chartDoubleMetricPerDay.create() }
  },

  // add new chart
  create: function () {
    var xAxisItems = $('#dataChartDoubleMetricPerDay ul.series li.serie:first-child ul.data li')
    var xAxisValues = []
    var xAxisCategories = []
    var counter = 0
    var interval = Math.ceil(xAxisItems.length / 10)

    xAxisItems.each(function () {
      xAxisValues.push($(this).children('span.fulldate').html())
      var text = $(this).children('span.date').html()
      if (xAxisItems.length > 10 && counter % interval > 0) text = ' '
      xAxisCategories.push(text)
      counter++
    })

    var maxValue = 0
    var metric1Name = $('#dataChartDoubleMetricPerDay ul.series li#metric1serie span.name').html()
    var metric1Values = $('#dataChartDoubleMetricPerDay ul.series li#metric1serie span.value')
    var metric1Data = []

    metric1Values.each(function () {
      metric1Data.push(parseInt($(this).html()))
      if (parseInt($(this).html()) > maxValue) {
        maxValue = parseInt($(this).html())
      }
    })

    var metric2Name = $('#dataChartDoubleMetricPerDay ul.series li#metric2serie span.name').html()
    var metric2Values = $('#dataChartDoubleMetricPerDay ul.series li#metric2serie span.value')
    var metric2Data = []

    metric2Values.each(function () {
      metric2Data.push(parseInt($(this).html()))
      if (parseInt($(this).html()) > maxValue) {
        maxValue = parseInt($(this).html())
      }
    })

    var tickInterval = Math.ceil(maxValue / 5)

    var containerWidth = $('#chartDoubleMetricPerDay').width()

    jsBackend.analytics.chartDoubleMetricPerDay.chart = new Highcharts.Chart({
      chart: {
        renderTo: 'chartDoubleMetricPerDay',
        height: 200,
        width: containerWidth,
        margin: [60, 0, 30, 40],
        defaultSeriesType: 'line',
        backgroundColor: 'transparent'
      },
      xAxis: {lineColor: '#CCC', lineWidth: 1, categories: xAxisCategories, color: '#000'},
      yAxis: {min: 0, max: maxValue, tickInterval: tickInterval, title: {text: ''}},
      credits: {enabled: false},
      tooltip: {formatter: function () { return '' + this.series.name + '
' + xAxisValues[this.point.x] + ': ' + this.y }},
      plotOptions: {
        line: {
          marker: {
            enabled: false,
            states: {hover: {enabled: true, symbol: 'circle', radius: 5, lineWidth: 1}}
          }
        },
        area: {
          marker: {
            enabled: false,
            states: {hover: {enabled: true, symbol: 'circle', radius: 5, lineWidth: 1}}
          }
        },
        column: {pointPadding: 0.2, borderWidth: 0},
        series: {fillOpacity: 0.3}
      },
      series: [{name: metric1Name, data: metric1Data, type: 'area'}, {name: metric2Name, data: metric2Data}],
      legend: {layout: 'horizontal', verticalAlign: 'top'}
    })
  },

  // destroy chart
  destroy: function () {
    jsBackend.analytics.chartDoubleMetricPerDay.chart.destroy()
  }
}
<commit_msg>Fix for Analytics charts<commit_after>/**
 * Interaction for the analytics module
 */
/* global Highcharts */
jsBackend.analytics = {
  $chartPieChart: null,
  $chartDoubleMetricPerDay: null
}

jsBackend.analytics.charts = {
  init: function () {
    jsBackend.analytics.$chartPieChart = $('#chartPieChart')
    jsBackend.analytics.$chartDoubleMetricPerDay = $('#chartDoubleMetricPerDay')

    if (jsBackend.analytics.$chartPieChart.length > 0 || jsBackend.analytics.$chartDoubleMetricPerDay.length > 0) {
      Highcharts.setOptions({
        colors: ['#2f77d1', '#021b45', '#ED561B', '#EDEF00', '#24CBE5', '#64E572', '#FF9655'],
        title: {text: ''},
        legend: {
          layout: 'vertical',
          borderWidth: 0,
          shadow: false,
          symbolPadding: 12,
          symbolWidth: 10,
          itemStyle: {cursor: 'pointer', color: '#000', lineHeight: '18px'},
          itemHoverStyle: {color: '#666'}
        }
      })
    }

    jsBackend.analytics.chartPieChart.init()
    jsBackend.analytics.chartDoubleMetricPerDay.init()
  }
}

jsBackend.analytics.chartPieChart = {
  chart: '',

  init: function () {
    if (jsBackend.analytics.$chartPieChart.length > 0) { jsBackend.analytics.chartPieChart.create() }
  },

  // add new chart
  create: function () {
    // variables
    var $pieChartValues = $('#dataChartPieChart ul.data li')
    var pieChartData = []

    $pieChartValues.each(function () {
      // variables
      var $this = $(this)

      pieChartData.push({
        name: $this.children('span.label').html(),
        y: parseInt($this.children('span.value').html()),
        percentage: parseInt($this.children('span.percentage').html())
      })
    })

    var containerWidth = jsBackend.analytics.$chartPieChart.width()

    jsBackend.analytics.chartPieChart.chart = new Highcharts.Chart({
      chart: {
        renderTo: 'chartPieChart',
        height: 200,
        width: containerWidth,
        margin: [0, 160, 0, 0],
        backgroundColor: 'transparent'
      },
      credits: {enabled: false},
      plotArea: {shadow: null, borderWidth: null, backgroundColor: null},
      tooltip: {
        formatter: function () {
          var percentage = String(this.point.percentage)
          return '' + this.point.name + ': ' + this.y + ' (' + percentage.substring(0, $.inArray('.', percentage) + 3) + '%)'
        },
        borderWidth: 2,
        shadow: false
      },
      plotOptions: {
        pie: {
          allowPointSelect: true,
          dataLabels: {
            enabled: false
          },
          showInLegend: true
        }
      },
      legend: {align: 'right'},
      series: [{type: 'pie', data: pieChartData}]
    })
  },

  // destroy chart
  destroy: function () {
    jsBackend.analytics.chartPieChart.chart.destroy()
  }
}

jsBackend.analytics.chartDoubleMetricPerDay = {
  chart: '',

  init: function () {
    if (jsBackend.analytics.$chartDoubleMetricPerDay.length > 0) { jsBackend.analytics.chartDoubleMetricPerDay.create() }
  },

  // add new chart
  create: function () {
    var xAxisItems = $('#dataChartDoubleMetricPerDay ul.series li.serie:first-child ul.data li')
    var xAxisValues = []
    var xAxisCategories = []
    var counter = 0
    var interval = Math.ceil(xAxisItems.length / 10)

    xAxisItems.each(function () {
      xAxisValues.push($(this).children('span.fulldate').html())
      var text = $(this).children('span.date').html()
      if (xAxisItems.length > 10 && counter % interval > 0) text = ' '
      xAxisCategories.push(text)
      counter++
    })

    var maxValue = 0
    var metric1Name = $('#dataChartDoubleMetricPerDay ul.series li#metric1serie span.name').html()
    var metric1Values = $('#dataChartDoubleMetricPerDay ul.series li#metric1serie span.value')
    var metric1Data = []

    metric1Values.each(function () {
      metric1Data.push(parseInt($(this).html()))
      if (parseInt($(this).html()) > maxValue) {
        maxValue = parseInt($(this).html())
      }
    })

    var metric2Name = $('#dataChartDoubleMetricPerDay ul.series li#metric2serie span.name').html()
    var metric2Values = $('#dataChartDoubleMetricPerDay ul.series li#metric2serie span.value')
    var metric2Data = []

    metric2Values.each(function () {
      metric2Data.push(parseInt($(this).html()))
      if (parseInt($(this).html()) > maxValue) {
        maxValue = parseInt($(this).html())
      }
    })

    var tickInterval = Math.ceil(maxValue / 5)

    var containerWidth = $('#chartDoubleMetricPerDay').width()

    jsBackend.analytics.chartDoubleMetricPerDay.chart = new Highcharts.Chart({
      chart: {
        renderTo: 'chartDoubleMetricPerDay',
        height: 200,
        width: containerWidth,
        margin: [60, 0, 30, 40],
        defaultSeriesType: 'line',
        backgroundColor: 'transparent'
      },
      xAxis: {lineColor: '#CCC', lineWidth: 1, categories: xAxisCategories, color: '#000'},
      yAxis: {min: 0, max: maxValue, tickInterval: tickInterval, title: {text: ''}},
      credits: {enabled: false},
      tooltip: {formatter: function () { return '' + this.series.name + '
' + xAxisValues[this.point.x] + ': ' + this.y }},
      plotOptions: {
        line: {
          marker: {
            enabled: false,
            states: {hover: {enabled: true, symbol: 'circle', radius: 5, lineWidth: 1}}
          }
        },
        area: {
          marker: {
            enabled: false,
            states: {hover: {enabled: true, symbol: 'circle', radius: 5, lineWidth: 1}}
          }
        },
        column: {pointPadding: 0.2, borderWidth: 0},
        series: {fillOpacity: 0.3}
      },
      series: [{name: metric1Name, data: metric1Data, type: 'area'}, {name: metric2Name, data: metric2Data}],
      legend: {layout: 'horizontal', verticalAlign: 'top'}
    })
  },

  // destroy chart
  destroy: function () {
    jsBackend.analytics.chartDoubleMetricPerDay.chart.destroy()
  }
}

$(jsBackend.analytics.charts.init)
<|endoftext|>


<commit_before>var IncomingCallBack = require('../constructors/callback');
var NameSpace = require('../constructors/namespace');
var routeController = require('./routeController');

var core;

var incomingCallbacks = {};
var outgoingCallbacks = {};
var nameSpaces = {};

var executionController = {

    initialize: function(samsaaraCore) {
        core = samsaaraCore;

        nameSpaces.core = new NameSpace('core', {});
        nameSpaces.internal = new NameSpace('internal', {
            callItBack: callItBack,
            callItBackError: callItBackError
        });
    },

    // Outgoing Execution

    execute: function(channel, route, executorArray, namespaceName, funcName, args) {

        var packet = {
            func: funcName,
            ns: namespaceName || 'core',
            args: Array.prototype.slice.call(args)
        };

        if (typeof args[args.length - 1] === 'function') {
            createCallBack(packet.args.pop(), executorArray, packet);
        }

        routeController.routeOutgoingPacket(channel, route, packet);
    },

    executeRaw: function(channel, route, executorArray, packet, callBack) {

        if (typeof callBack === 'function') {
            createCallBack(callBack, executorArray, packet);
        }

        routeController.routeOutgoingPacket(channel, route, packet);
    },

    // Incoming Execution

    executeFunction: function(executor, context, incomingPacket, callBackGenerator) {

        var functionName = incomingPacket.func;
        var namespaceName = incomingPacket.ns || 'core';
        var namespace = this.nameSpace(namespaceName);
        var namespaceMethods;
        var messageArgs;
        var theCallBack;
        var callbackID;

        if (namespace !== undefined) {

            namespaceMethods = namespace.methods;

            if (typeof namespaceMethods[functionName] === 'function') {

                messageArgs = incomingPacket.args || [];

                callBackGenerator = callBackGenerator || generateOutgoingCallBackClosure;
                callbackID = incomingPacket.callBack;

                if (typeof callbackID === 'string' && callbackID.match(/^([a-zA-Z0-9\.]+)$/)) {
                    theCallBack = outgoingCallbacks[callbackID] = callBackGenerator(callbackID, executor);
                    messageArgs.push(theCallBack);
                }

                namespaceMethods[functionName].apply(context, messageArgs);

            } else {
                console.error('Samsaara Method Execution ERROR: Call by:', executor.id, ':', functionName, 'is not an exposed Samsaara Object that can be executed.');
            }

        } else {
            console.error('Samsaara Method Execution ERROR: Call by:', executor.id, ':', namespaceName, 'is not valid namespace.');
        }
    },

    // Exported to Core

    createNamespace: function(namespaceName, methods) {

        var nameSpace = null;

        if (namespaceName !== 'core' && namespaceName !== 'internal') {
            nameSpace = new NameSpace(namespaceName, methods);
            nameSpaces[namespaceName] = nameSpace;
        }

        return core;
    },

    nameSpace: function(namespaceName) {
        return nameSpaces[namespaceName];
    },

    expose: function(set) {
        this.nameSpace('core').expose(set);
        return core;
    }
};

// a method to process a packet for multiple executors
// args is initially an arguments object
function processPacket(executorArray, packet, args) {

    if (typeof args[args.length - 1] === 'function') {
        args = Array.prototype.slice.call(args);
        createCallBack(args.pop(), executorArray, packet);
    }

    packet.args = args;

    return packet;
}

// Incoming CallBack Generator
// Creates an expected Callback method, whose index is sent to clients.
// The callback will expect a certain number of processes/clients to execute before getting deleted/set to undefined.
function createCallBack(theCallBack, executorArray, packet) {

    var incomingCallback = new IncomingCallBack(theCallBack, executorArray, destroyCallBack);
    var callbackID = incomingCallback.callbackID;

    incomingCallbacks[callbackID] = incomingCallback;
    packet.callBack = callbackID;

    return incomingCallback;
}

function destroyCallBack(callbackID) {
    incomingCallbacks[callbackID] = undefined;
}

// Outgoing CallBack Generator
// Returns a function to send a message answering a callBack request sent from the client
function generateOutgoingCallBackClosure(callbackID, executor) {

    var theCallBack = function() {
        var args = Array.prototype.slice.call(arguments),
            packet = {
                ns: 'internal',
                func: 'callItBack',
                args: [callbackID, args]
            },
            aCallBack;

        if (typeof args[args.length - 1] !== 'function') {
            executor.executeRaw(packet);
        } else {
            aCallBack = args.pop();
            executor.executeRaw(packet, aCallBack);
        }

        outgoingCallbacks[callbackID] = undefined;
    };

    return theCallBack;
}

// Exposed CallBack Execution Method
// Allows the client to execute an indexed method that was stored for callback
function callItBack(callbackID, args) {

    var executor = this;
    var executorID = executor.id;
    var theCallBack = incomingCallbacks[callbackID];

    if (theCallBack !== undefined && args instanceof Array) {

        if (typeof arguments[arguments.length - 1] === 'function') {
            args.push(arguments[arguments.length - 1]);
        }

        theCallBack.executeCallBack(executorID, executor, args);
    }
}

// Exposed CallBack Execution Error Method
// Allows the client to execute an indexed method that was stored for callback
function callItBackError(callbackID, args) {

    var executor = this;
    var executorID = executor.id;
    var theCallBack = incomingCallbacks[callbackID];

    if (theCallBack !== undefined) {
        theCallBack.callBackError(executorID, executor, args);
    }
}

module.exports = executionController;
<commit_msg>Not referring to this in controller methods.<commit_after>var IncomingCallBack = require('../constructors/callback');
var NameSpace = require('../constructors/namespace');
var routeController = require('./routeController');

var core;

var incomingCallbacks = {};
var outgoingCallbacks = {};
var nameSpaces = {};

var executionController = {

    initialize: function(samsaaraCore) {
        core = samsaaraCore;

        nameSpaces.core = new NameSpace('core', {});
        nameSpaces.internal = new NameSpace('internal', {
            callItBack: callItBack,
            callItBackError: callItBackError
        });
    },

    // Outgoing Execution

    execute: function(channel, route, executorArray, namespaceName, funcName, args) {

        var packet = {
            func: funcName,
            ns: namespaceName || 'core',
            args: Array.prototype.slice.call(args)
        };

        if (typeof args[args.length - 1] === 'function') {
            createCallBack(packet.args.pop(), executorArray, packet);
        }

        routeController.routeOutgoingPacket(channel, route, packet);
    },

    executeRaw: function(channel, route, executorArray, packet, callBack) {

        if (typeof callBack === 'function') {
            createCallBack(callBack, executorArray, packet);
        }

        routeController.routeOutgoingPacket(channel, route, packet);
    },

    // Incoming Execution

    executeFunction: function(executor, context, incomingPacket, callBackGenerator) {

        var functionName = incomingPacket.func;
        var namespaceName = incomingPacket.ns || 'core';
        var namespace = nameSpaces[namespaceName];
        var namespaceMethods;
        var messageArgs;
        var theCallBack;
        var callbackID;

        if (namespace !== undefined) {

            namespaceMethods = namespace.methods;

            if (typeof namespaceMethods[functionName] === 'function') {

                messageArgs = incomingPacket.args || [];

                callBackGenerator = callBackGenerator || generateOutgoingCallBackClosure;
                callbackID = incomingPacket.callBack;

                if (typeof callbackID === 'string' && callbackID.match(/^([a-zA-Z0-9\.]+)$/)) {
                    theCallBack = outgoingCallbacks[callbackID] = callBackGenerator(callbackID, executor);
                    messageArgs.push(theCallBack);
                }

                namespaceMethods[functionName].apply(context, messageArgs);

            } else {
                console.error('Samsaara Method Execution ERROR: Call by:', executor.id, ':', functionName, 'is not an exposed Samsaara Object that can be executed.');
            }

        } else {
            console.error('Samsaara Method Execution ERROR: Call by:', executor.id, ':', namespaceName, 'is not valid namespace.');
        }
    },

    // Exported to Core

    createNamespace: function(namespaceName, methods) {

        var nameSpace = null;

        if (namespaceName !== 'core' && namespaceName !== 'internal') {
            nameSpace = new NameSpace(namespaceName, methods);
            nameSpaces[namespaceName] = nameSpace;
        }

        return core;
    },

    nameSpace: function(namespaceName) {
        return nameSpaces[namespaceName];
    },

    expose: function(set) {
        nameSpaces.core.expose(set);
        return core;
    }
};

// a method to process a packet for multiple executors
// args is initially an arguments object
function processPacket(executorArray, packet, args) {

    if (typeof args[args.length - 1] === 'function') {
        args = Array.prototype.slice.call(args);
        createCallBack(args.pop(), executorArray, packet);
    }

    packet.args = args;

    return packet;
}

// Incoming CallBack Generator
// Creates an expected Callback method, whose index is sent to clients.
// The callback will expect a certain number of processes/clients to execute before getting deleted/set to undefined.
function createCallBack(theCallBack, executorArray, packet) {

    var incomingCallback = new IncomingCallBack(theCallBack, executorArray, destroyCallBack);
    var callbackID = incomingCallback.callbackID;

    incomingCallbacks[callbackID] = incomingCallback;
    packet.callBack = callbackID;

    return incomingCallback;
}

function destroyCallBack(callbackID) {
    incomingCallbacks[callbackID] = undefined;
}

// Outgoing CallBack Generator
// Returns a function to send a message answering a callBack request sent from the client
function generateOutgoingCallBackClosure(callbackID, executor) {

    var theCallBack = function() {
        var args = Array.prototype.slice.call(arguments),
            packet = {
                ns: 'internal',
                func: 'callItBack',
                args: [callbackID, args]
            },
            aCallBack;

        if (typeof args[args.length - 1] !== 'function') {
            executor.executeRaw(packet);
        } else {
            aCallBack = args.pop();
            executor.executeRaw(packet, aCallBack);
        }

        outgoingCallbacks[callbackID] = undefined;
    };

    return theCallBack;
}

// Exposed CallBack Execution Method
// Allows the client to execute an indexed method that was stored for callback
function callItBack(callbackID, args) {

    var executor = this;
    var executorID = executor.id;
    var theCallBack = incomingCallbacks[callbackID];

    if (theCallBack !== undefined && args instanceof Array) {

        if (typeof arguments[arguments.length - 1] === 'function') {
            args.push(arguments[arguments.length - 1]);
        }

        theCallBack.executeCallBack(executorID, executor, args);
    }
}

// Exposed CallBack Execution Error Method
// Allows the client to execute an indexed method that was stored for callback
function callItBackError(callbackID, args) {

    var executor = this;
    var executorID = executor.id;
    var theCallBack = incomingCallbacks[callbackID];

    if (theCallBack !== undefined) {
        theCallBack.callBackError(executorID, executor, args);
    }
}

module.exports = executionController;
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/*
   "pageSets" is a list of lists.
     - Before each sublist:
           Run chrome.browingData.remove and close the connections.
     - Before each url in a sublist:
           Close the connections.
*/
var pageSets = [
    ["http://superfastpageload/web-page-replay-generate-200"],

    // Load url pairs without clearing browser data (e.g. cache) in-between.
    ["http://go.com/",
     "http://espn.go.com/"],
    ["http://www.amazon.com/",
     "http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2/"],
    ["http://www.baidu.com/",
     "http://www.baidu.com/s?wd=obama"],
    ["http://www.bing.com/",
     "http://www.bing.com/search?q=cars"],
    ["http://www.ebay.com/",
     "http://fashion.ebay.com/womens-clothing"],
    ["http://www.google.com/",
     "http://www.google.com/search?q=dogs"],
    ["http://www.yandex.ru/",
     "http://yandex.ru/yandsearch?text=obama&lr=84"],
    ["http://www.youtube.com",
     "http://www.youtube.com/watch?v=xvN9Ri1GmuY&feature=g-sptl&cid=inp-hs-edt"],

    ["http://ameblo.jp/"],
    ["http://en.rakuten.co.jp/"],
    ["http://en.wikipedia.org/wiki/Lady_gaga"],
    ["http://news.google.co.in"],
    ["http://plus.google.com/"],  // iframe error (result of no cookies?)
    ["http://www.163.com/"],
    ["http://www.apple.com/"],
    ["http://www.bbc.co.uk/"],
    ["http://www.cnet.com/"],
    ["http://www.msn.com/"],
    ["http://www.nytimes.com/"],
    ["http://www.taobao.com/"],
    ["http://www.yahoo.co.jp/"],

    // HTTPS pages.
    ["https://wordpress.com/"],
    ["https://www.conduit.com/"],
    ["https://www.facebook.com",
     "https://www.facebook.com/barackobama"],
];

/*
    // Not included (need further investigation).
    ["http://twitter.com/BarackObama",
    "http://twitter.com/search?q=pizza"], // large variance on second page
    ["http://www.fc2.com/"],      // slow
    ["http://sina.com.cn/"],      // slow
    ["http://www.mail.ru/"],      // long load time (30s+)
    ["http://www.sohu.com/"],     // load does not finish (even without WPR)

    // Not included (trimmed pageSets to keep test under 10 minutes).
    ["http://sfbay.craigslist.org/",
    "http://sfbay.craigslist.org/search/sss?query=flowers"],
    ["http://www.flickr.com/",
    "http://www.flickr.com/photos/tags/flowers"],
    ["http://www.linkedin.com/",
    "http://www.linkedin.com/in/jeffweiner08"],
    ["http://www.yahoo.com/",
    "http://search.yahoo.com/search?p=disney"],
    ["http://googleblog.blogspot.com/"],
    ["http://www.adobe.com/reader/"],
    ["http://www.cnn.com/"],
    ["http://www.imdb.com/"],
    ["http://www.qq.com/"],
*/
<commit_msg>Remove youtube.com from the netsim test.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/*
   "pageSets" is a list of lists.
     - Before each sublist:
           Run chrome.browingData.remove and close the connections.
     - Before each url in a sublist:
           Close the connections.
*/
var pageSets = [
    ["http://superfastpageload/web-page-replay-generate-200"],

    // Load url pairs without clearing browser data (e.g. cache) in-between.
    ["http://go.com/",
     "http://espn.go.com/"],
    ["http://www.amazon.com/",
     "http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2/"],
    ["http://www.baidu.com/",
     "http://www.baidu.com/s?wd=obama"],
    ["http://www.bing.com/",
     "http://www.bing.com/search?q=cars"],
    ["http://www.ebay.com/",
     "http://fashion.ebay.com/womens-clothing"],
    ["http://www.google.com/",
     "http://www.google.com/search?q=dogs"],
    ["http://www.yandex.ru/",
     "http://yandex.ru/yandsearch?text=obama&lr=84"],

    ["http://ameblo.jp/"],
    ["http://en.rakuten.co.jp/"],
    ["http://en.wikipedia.org/wiki/Lady_gaga"],
    ["http://news.google.co.in"],
    ["http://plus.google.com/"],  // iframe error (result of no cookies?)
    ["http://www.163.com/"],
    ["http://www.apple.com/"],
    ["http://www.bbc.co.uk/"],
    ["http://www.cnet.com/"],
    ["http://www.msn.com/"],
    ["http://www.nytimes.com/"],
    ["http://www.taobao.com/"],
    ["http://www.yahoo.co.jp/"],

    // HTTPS pages.
    ["https://wordpress.com/"],
    ["https://www.conduit.com/"],
    ["https://www.facebook.com",
     "https://www.facebook.com/barackobama"],
];

/*
    // http://code.google.com/p/chromium/issues/detail?id=133822
    ["http://www.youtube.com",
     "http://www.youtube.com/watch?v=xvN9Ri1GmuY&feature=g-sptl&cid=inp-hs-edt"],

    // Not included (need further investigation).
    ["http://twitter.com/BarackObama",
    "http://twitter.com/search?q=pizza"], // large variance on second page
    ["http://www.fc2.com/"],      // slow
    ["http://sina.com.cn/"],      // slow
    ["http://www.mail.ru/"],      // long load time (30s+)
    ["http://www.sohu.com/"],     // load does not finish (even without WPR)

    // Not included (trimmed pageSets to keep test under 10 minutes).
    ["http://sfbay.craigslist.org/",
    "http://sfbay.craigslist.org/search/sss?query=flowers"],
    ["http://www.flickr.com/",
    "http://www.flickr.com/photos/tags/flowers"],
    ["http://www.linkedin.com/",
    "http://www.linkedin.com/in/jeffweiner08"],
    ["http://www.yahoo.com/",
    "http://search.yahoo.com/search?p=disney"],
    ["http://googleblog.blogspot.com/"],
    ["http://www.adobe.com/reader/"],
    ["http://www.cnn.com/"],
    ["http://www.imdb.com/"],
    ["http://www.qq.com/"],
*/
<|endoftext|>


<commit_before>var config   = require('./config'),
    // TODO: sniff proper transitonend event name
    endEvent = 'transitionend'

/**
 *  stage:
 *  1 = enter
 *  2 = leave
 */
module.exports = function (el, stage, changeState, init) {

    // TODO: directly return if IE9

    var className         = el.sd_trans_class,
        classList         = el.classList,
        lastLeaveCallback = el.sd_trans_cb

    // in sd-repeat, the sd-transition directive
    // might not have been processed yet
    if (!className) {
        className = el.getAttribute(config.transClassAttr)
    }

    // TODO: optional duration which
    //       can override the default transitionend event

    // if no transition, just call changeState sync.
    // this is internal API and the changeState callback
    // will always contain only dom manipulations that
    // doesn't care about the sync/async-ness of this method.
    if (init || !className) {
        return changeState()
    }

    if (stage > 0) { // enter

        // cancel unfinished leave transition
        if (lastLeaveCallback) {
            el.removeEventListener(endEvent, lastLeaveCallback)
            el.sd_trans_cb = null
        }

        // set to hidden state before appending
        classList.add(className)
        // append
        changeState()
        // force a layout so transition can be triggered
        /* jshint unused: false */
        var forceLayout = el.clientHeight
        // trigger transition
        classList.remove(className)

    } else { // leave

        // trigger hide transition
        classList.add(className)
        var onEnd = function () {
            el.removeEventListener(endEvent, onEnd)
            el.sd_trans_cb = null
            // actually remove node here
            changeState()
            classList.remove(className)
        }
        // attach transition end listener
        el.addEventListener(endEvent, onEnd)
        el.sd_trans_cb = onEnd

    }
}<commit_msg>sniff transitionend event<commit_after>var config   = require('./config'),
    endEvent = sniffTransitionEndEvent()

/**
 *  stage:
 *  1 = enter
 *  2 = leave
 */
module.exports = function (el, stage, changeState, init) {

    if (!endEvent || init) {
        return changeState()
    }

    var className =
        el.sd_trans_class ||
        // in sd-repeat, the sd-transition directive
        // might not have been processed yet
        el.getAttribute(config.transClassAttr)

    if (!className) {
        return changeState()
    }

    var classList         = el.classList,
        lastLeaveCallback = el.sd_trans_cb

    if (stage > 0) { // enter

        // cancel unfinished leave transition
        if (lastLeaveCallback) {
            el.removeEventListener(endEvent, lastLeaveCallback)
            el.sd_trans_cb = null
        }

        // set to hidden state before appending
        classList.add(className)
        // append
        changeState()
        // force a layout so transition can be triggered
        /* jshint unused: false */
        var forceLayout = el.clientHeight
        // trigger transition
        classList.remove(className)

    } else { // leave

        // trigger hide transition
        classList.add(className)
        var onEnd = function () {
            el.removeEventListener(endEvent, onEnd)
            el.sd_trans_cb = null
            // actually remove node here
            changeState()
            classList.remove(className)
        }
        // attach transition end listener
        el.addEventListener(endEvent, onEnd)
        el.sd_trans_cb = onEnd

    }
}

/**
 *  Sniff proper transition end event name
 */
function sniffTransitionEndEvent () {
    var el = document.createElement('div'),
        defaultEvent = 'transitionend',
        events = {
            'transition'       : defaultEvent,
            'MozTransition'    : defaultEvent,
            'WebkitTransition' : 'webkitTransitionEnd'
        }
    for (var name in events) {
        if (el.style[name] !== undefined) {
            return events[name]
        }
    }
}<|endoftext|>


<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : mapChartFlowModel.js
* Module : Lib::DataTier::mapChartFlowModel
* Location : /lib/dataTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-15   Filippo Rampado    Initial code
* =========================================================
*/
var FlowModel = require('./flowModel.js');
var Helper = require('../../helpers/functionHelper.js');

function MapChartFlowModel(params) {
	if(params===undefined || params.ID===undefined || typeof params.ID !== 'string'|| params.ID.trim() === ''){ // ID field is required
		console.log('Error: 232');
		return;
	}

	params.type = 'MapChartFlow';
	this.parent.constructor.call(this, params);

	this._longitudeKey=null;
	this._latitudeKey=null;
	this._longitudeFormat='coordinates';
	this._latitudeFormat='coordinates';
	this._flowColor=null;//will be random on frontEnd
	this._marker={
		type: 'shape',//shape, icon, text
		shape: 'circle',//circle, triangle, square, diamond
		icon: null,//path
		text: null,//string
	};
	this._trace={
		type: 'none',//none, line, poly
		coordinates: []
	};
	this._maxItems=50;//items displayed
	this._maxItemsSaved=500; //items saved

	if(params.longitudeKey!==undefined && typeof params.longitudeKey === 'string'){
		this._longitudeKey=params.longitudeKey;
	}
	if(params.latitudeKey!==undefined && typeof params.latitudeKey === 'string'){
		this._latitudeKey=params.latitudeKey;
	}
	if(params.longitudeFormat!==undefined && Helper.isValidMapFormat(params.longitudeFormat)){
		this._longitudeFormat=params.longitudeFormat;
	}
	if(params.latitudeFormat!==undefined && Helper.isValidMapFormat(params.latitudeFormat)){
		this._latitudeFormat=params.latitudeFormat;
	}
	if(params.flowColor!==undefined && Helper.isHEX(params.flowColor)){
		this._flowColor=params.flowColor;
	}
	if(params.marker!==undefined && Helper.isValidMapMarker(params.marker)){
		this._marker=params.marker;
	}
	if(params.trace!==undefined && Helper.isValidTrace(params.trace)){
		this._trace=params.trace;
	}
	if(params.maxItems!==undefined && typeof params.maxItems==='number' && params.maxItems>=0){
		this._maxItems=params.maxItems;
	}
	if(params.maxItemsSaved!==undefined && typeof params.maxItemsSaved==='number' && params.maxItemsSaved>=0){
		this._maxItemsSaved=params.maxItemsSaved;
	}
}

MapChartFlowModel.prototype = Object.create(FlowModel.prototype);
MapChartFlowModel.prototype.constructor = MapChartFlowModel;
MapChartFlowModel.prototype.parent = FlowModel.prototype;

MapChartFlowModel.prototype.updateProperties = function(params){
	if(params.longitudeKey!==undefined && typeof params.longitudeKey === 'string'){
		this._longitudeKey=params.longitudeKey;
	}
	if(params.latitudeKey!==undefined && typeof params.latitudeKey === 'string'){
		this._latitudeKey=params.latitudeKey;
	}
	if(params.longitudeFormat!==undefined && Helper.isValidMapFormat(params.longitudeFormat)){
		this._longitudeFormat=params.longitudeFormat;
	}
	if(params.latitudeFormat!==undefined && Helper.isValidMapFormat(params.latitudeFormat)){
		this._latitudeFormat=params.latitudeFormat;
	}
	if(params.flowColor!==undefined && Helper.isHEX(params.flowColor)){
		this._flowColor=params.flowColor;
	}
	if(params.marker!==undefined && Helper.isValidMapMarker(params.marker)){
		this._marker=params.marker;
	}
	if(params.trace!==undefined && Helper.isValidTrace(params.trace)){
		this._trace=params.trace;
	}
	if(params.maxItems!==undefined && typeof params.maxItems==='number' && params.maxItems>=0){
		this._maxItems=params.maxItems;
	}
	if(params.maxItemsSaved!==undefined && typeof params.maxItemsSaved==='number' && params.maxItemsSaved>=0){
		this._maxItemsSaved=params.maxItemsSaved;
	}
};

MapChartFlowModel.prototype.addRecord = function(record){
	if(record!==undefined && record!==null && typeof record === 'object'){
		this._records.push(record);
		var index=this._records.length-1;
		var ID=this.generateNorrisRecordID(index);
		this._records[index].norrisRecordID=ID;
		this.validateRecord(index);
		return ID;
	}
	console.log('Error: 133');
	return 133;
};

MapChartFlowModel.prototype.updateRecord = function(ID, record){
	if (record === undefined || record === null || typeof record !== 'object'|| Array.isArray(record)){
		return 131;
	}
	if (typeof ID==='string' && ID.indexOf(this._ID) !== -1) {
		var records=this._records.length;
		var i=0;
		var found=false;
		while (i<records && (!found)){
			if (this._records[i].norrisRecordID===ID){
				found=true;
			}
			else{
				i++;
			}
		}//while
		if (found){//in records[i] there is the ID
			this._records[i]=record;
			this.validateRecord(i);
			return true;
		}
		//no ID in records
		return 132;
	}
	//invalid ID
	return 132;
};

MapChartFlowModel.prototype.deleteRecord = function(ID){
	if (ID!==undefined && typeof ID==='string' && ID.indexOf(this._ID) !== -1) {
		var records=this._records.length;
		var i=0;
		var found=false;
		while (i<records && (!found)){
			if (this._records[i].norrisRecordID===ID){
				found=true;
			}
			else{
				i++;
			}
		}//while
		if (found){//in records[i] there is the ID_index
			this._records.splice(i, 1);
			return true;
		}
	}
	return 134;
};

MapChartFlowModel.prototype.getProperties = function(){
	var prop=this.parent.getProperties.call(this);
	prop.longitudeKey=this._longitudeKey;
	prop.latitudeKey=this._latitudeKey;
	prop.longitudeFormat=this._longitudeFormat;
	prop.latitudeFormat=this._latitudeFormat;
	prop.flowColor=this._flowColor;
	prop.marker={
		type: this._marker.type,
		shape: this._marker.shape,
		icon: this._marker.icon,
		text: this._marker.text,
	};
	prop.trace={
		type: this._trace.type,
		coordinates: this._trace.coordinates
	};
	prop.maxItems=this._maxItems=50;
	prop.maxItemsSaved=this._maxItemsSaved=500;
	return prop;
};

module.exports = MapChartFlowModel;<commit_msg>fix test<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : mapChartFlowModel.js
* Module : Lib::DataTier::mapChartFlowModel
* Location : /lib/dataTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-15   Filippo Rampado    Initial code
* =========================================================
*/
var FlowModel = require('./flowModel.js');
var Helper = require('../../helpers/functionHelper.js');

function MapChartFlowModel(params) {
	if(params===undefined || params.ID===undefined || typeof params.ID !== 'string'|| params.ID.trim() === ''){ // ID field is required
		console.log('Error: 232');
		return;
	}

	params.type = 'MapChartFlow';
	this.parent.constructor.call(this, params);

	this._longitudeKey=null;
	this._latitudeKey=null;
	this._longitudeFormat='coordinates';
	this._latitudeFormat='coordinates';
	this._flowColor=null;//will be random on frontEnd
	this._marker={
		type: 'shape',//shape, icon, text
		shape: 'circle',//circle, triangle, square, diamond
		//icon: null,//path
		//text: null,//string
	};
	this._trace={
		type: 'none',//none, line, poly
		coordinates: []
	};
	this._maxItems=50;//items displayed
	this._maxItemsSaved=500; //items saved

	if(params.longitudeKey!==undefined && typeof params.longitudeKey === 'string'){
		this._longitudeKey=params.longitudeKey;
	}
	if(params.latitudeKey!==undefined && typeof params.latitudeKey === 'string'){
		this._latitudeKey=params.latitudeKey;
	}
	if(params.longitudeFormat!==undefined && Helper.isValidMapFormat(params.longitudeFormat)){
		this._longitudeFormat=params.longitudeFormat;
	}
	if(params.latitudeFormat!==undefined && Helper.isValidMapFormat(params.latitudeFormat)){
		this._latitudeFormat=params.latitudeFormat;
	}
	if(params.flowColor!==undefined && Helper.isHEX(params.flowColor)){
		this._flowColor=params.flowColor;
	}
	if(params.marker!==undefined && Helper.isValidMapMarker(params.marker)){
		this._marker=params.marker;
	}
	if(params.trace!==undefined && Helper.isValidTrace(params.trace)){
		this._trace=params.trace;
	}
	if(params.maxItems!==undefined && typeof params.maxItems==='number' && params.maxItems>=0){
		this._maxItems=params.maxItems;
	}
	if(params.maxItemsSaved!==undefined && typeof params.maxItemsSaved==='number' && params.maxItemsSaved>=0){
		this._maxItemsSaved=params.maxItemsSaved;
	}
}

MapChartFlowModel.prototype = Object.create(FlowModel.prototype);
MapChartFlowModel.prototype.constructor = MapChartFlowModel;
MapChartFlowModel.prototype.parent = FlowModel.prototype;

MapChartFlowModel.prototype.updateProperties = function(params){
	if(params.longitudeKey!==undefined && typeof params.longitudeKey === 'string'){
		this._longitudeKey=params.longitudeKey;
	}
	if(params.latitudeKey!==undefined && typeof params.latitudeKey === 'string'){
		this._latitudeKey=params.latitudeKey;
	}
	if(params.longitudeFormat!==undefined && Helper.isValidMapFormat(params.longitudeFormat)){
		this._longitudeFormat=params.longitudeFormat;
	}
	if(params.latitudeFormat!==undefined && Helper.isValidMapFormat(params.latitudeFormat)){
		this._latitudeFormat=params.latitudeFormat;
	}
	if(params.flowColor!==undefined && Helper.isHEX(params.flowColor)){
		this._flowColor=params.flowColor;
	}
	if(params.marker!==undefined && Helper.isValidMapMarker(params.marker)){
		this._marker=params.marker;
	}
	if(params.trace!==undefined && Helper.isValidTrace(params.trace)){
		this._trace=params.trace;
	}
	if(params.maxItems!==undefined && typeof params.maxItems==='number' && params.maxItems>=0){
		this._maxItems=params.maxItems;
	}
	if(params.maxItemsSaved!==undefined && typeof params.maxItemsSaved==='number' && params.maxItemsSaved>=0){
		this._maxItemsSaved=params.maxItemsSaved;
	}
};

MapChartFlowModel.prototype.addRecord = function(record){
	if(record!==undefined && record!==null && typeof record === 'object'){
		this._records.push(record);
		var index=this._records.length-1;
		var ID=this.generateNorrisRecordID(index);
		this._records[index].norrisRecordID=ID;
		this.validateRecord(index);
		return ID;
	}
	console.log('Error: 133');
	return 133;
};

MapChartFlowModel.prototype.updateRecord = function(ID, record){
	if (record === undefined || record === null || typeof record !== 'object'|| Array.isArray(record)){
		return 131;
	}
	if (typeof ID==='string' && ID.indexOf(this._ID) !== -1) {
		var records=this._records.length;
		var i=0;
		var found=false;
		while (i<records && (!found)){
			if (this._records[i].norrisRecordID===ID){
				found=true;
			}
			else{
				i++;
			}
		}//while
		if (found){//in records[i] there is the ID
			this._records[i]=record;
			this.validateRecord(i);
			return true;
		}
		//no ID in records
		return 132;
	}
	//invalid ID
	return 132;
};

MapChartFlowModel.prototype.deleteRecord = function(ID){
	if (ID!==undefined && typeof ID==='string' && ID.indexOf(this._ID) !== -1) {
		var records=this._records.length;
		var i=0;
		var found=false;
		while (i<records && (!found)){
			if (this._records[i].norrisRecordID===ID){
				found=true;
			}
			else{
				i++;
			}
		}//while
		if (found){//in records[i] there is the ID_index
			this._records.splice(i, 1);
			return true;
		}
	}
	return 134;
};

MapChartFlowModel.prototype.getProperties = function(){
	var prop=this.parent.getProperties.call(this);
	prop.longitudeKey=this._longitudeKey;
	prop.latitudeKey=this._latitudeKey;
	prop.longitudeFormat=this._longitudeFormat;
	prop.latitudeFormat=this._latitudeFormat;
	prop.flowColor=this._flowColor;
	prop.marker=this._marker;
	prop.trace=this._trace;
	prop.maxItems=this._maxItems=50;
	prop.maxItemsSaved=this._maxItemsSaved=500;
	return prop;
};

module.exports = MapChartFlowModel;<|endoftext|>


<commit_before>/**
 * Created by binarylu on 3/18/16.
 */

var github_api = 'https://api.github.com';

var token = "";
var user = "";
var repo = "";
var commit_cond = "";
var default_comment = "";

var postfix = {
    c: ".c",
    cpp: ".cpp",
    java: ".java",
    python: ".py",
    csharp: ".cs",
    javascript: ".js",
    ruby: ".rb",
    swift: ".swift",
    golang: ".go",
    base: ".sh",
    mysql: ".sql"
};

$(function(){
    var reg = new RegExp('submissions');
    if (window.location.pathname.match(reg) !== null)
        return false;
    chrome.storage.sync.get({
        token: '',
        oauth_token: '',
        user: '',
        repo_name: '',
        commit: ["accepted", "time limit exceeded", "compile error", "runtime error"],
        comment: ''
    }, function(items) {
        if(chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError.message);
            return;
        }
        token = items.oauth_token;
        user = items.user;
        repo = items.repo_name;
        commit_cond = items.commit;
        default_comment = items.comment;

        upload_problem();
        if (items.token !== '' && items.oauth_token === '') {
            var $bulletin = $("");
            $("code-button").after($bulletin);
            var content = "LeetCode Extension does not support personal access token any more, please go to option page to login with OAuth.";
            $("#bulletin").html(content);
            $("#bulletin").css("color", "red");
        }

        if (token && user && repo) {
            add_node();
            $("#readme_button").click(restore);
            // $("#commit_readme").click({from: "commit_readme"}, commit);
            // $("#commit_question").click({from: "commit_question"}, commit);
            document.getElementById("commit_readme").onclick=function(){commit("commit_readme");};
            document.getElementById("commit_question").onclick=function(){commit("commit_question");};
            // submit button
            $("#button1").click(function() {
                $("#commit_status").html("");
            });
            $("#filename").val(get_filename());
            $('select[name=lang]').change(function () {
                var ext = get_extension();
                var filename = get_filename();
                filename = filename.substring(0, filename.lastIndexOf(".")) + ext;
                $("#filename").val(filename);
            });
            // result of submit
            $("#result-state").bind("DOMSubtreeModified", function() {
                var state = get_state("submit");
                if (state !== "" && $.inArray(state, commit_cond) != -1) {
                    commit("");
                }
            });
        } else {
            console.log("token: " + token);
            console.log("user: " + token);
            console.log("repo: " + token);
        }
    });
});

function add_node() {
    var $buttons = $("" +
        "<button type='button' class='btn btn-success' id='commit_question'>Add Question</button> " +
        "<button type='button' class='btn btn-success' data-toggle='modal' data-target='#readme' id='readme_button'>Add 'README.md'</button>" +
        "");
    var $div = $('' +
        '
' +
            '<form class="form-inline">' +
                '
' +
                    '
' +
                        '
' +
                            '' +
                                'Filename	' +
                            '' +
                                '<input type="text" class="form-control" id="filename" placeholder="Filename">	' +
                            '' +
                                'Comment	' +
                            '' +
                                '<input style="width:100%" type="text" class="form-control" id="code_message" placeholder="Input the comment for git commits">	' +
                        '
' +
                    '
' +
                '
' +
            '</form>' +
        '
');
    var $modal = $('' +
        '
' +
            '
' +
                '
' +
                    '
' +
                        '<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>' +
                        '
README.md
' +
                    '
' +
                    '
' +
                        'The following content will be commit to your Github repository.' +
                        '<textarea id="readme_content" class="form-control" rows="10"></textarea>
' +
                        '<input id="readme_message" type="text" class="form-control" placeholder="Input comments for git commit">' +
                    '
' +
                    '
' +
                        '' +
                        '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>' +
                        '<button type="button" class="btn btn-primary" id="commit_readme">Commit</button>' +
                    '
' +
                '
' +
            '
' +
        '
');
    var $code = $("" +
        "<textarea id='code_content' style='display:none'></textarea>");

    $("code-button").after($buttons);
    $("div.action").before($div);
    $("body").append($modal).append($code);
    $("#code_message").val(default_comment);

    /* Only by this, the variable in original page can be got.
    * Even using jQuery like before can not get the variable in original page */
    var script = document.createElement("script");
    script.innerHTML = "var lxk_editor = {};" +
        "$(function(){" +
            "$('.editor').attr('id', 'ace_editor_id');" +
            "lxk_editor = ace.edit('ace_editor_id');" +
            "get_code();" +
            "$('select[name=lang]').change(get_code);" +
            "$('#button0').click(get_code);" +
            "$('#button1').click(get_code);" +
        "});" +
        "function get_code() {" +
            "$('#code_content').val(lxk_editor.getValue());" +
        "}";
    document.body.appendChild(script);
}

function commit(from) {
    $("#commit_status").html("");
    var filename = "";
    if (from == "commit_readme") {
        filename = "README.md";
    } else if (from == "commit_question") {
        filename = "Question.md";
    } else {
        filename = get_filename();
    }
    filename = get_path() + "/" + filename;
    get_file(filename, update_file, update_file);
}

function restore() {
    var filename = "README.md";
    filename = get_path() + "/" + filename;
    get_file(filename, restore_file);
    $("#readme_message").val(default_comment);
}

function get_file(filename, fsucc, ferr) {
    $.ajax({
        url: github_api + '/repos/' + user  + '/' + repo + '/contents/' + filename,
        type: 'get',
        dataType: 'json',
        async: true,
        beforeSend: function(request) {
            request.setRequestHeader("Authorization", "token " + token);
        },
        success: function(jsonData) {
            if (typeof(jsonData)=='undefined' || !jsonData) jsonData = {};
            var sha = jsonData.sha;
            var file_content = jsonData.content;
            fsucc(filename, sha, file_content);
        },
        error: function(err) {
            if (err.status == 404) {
                if(typeof ferr === "function") {
                    ferr(filename);
                }
            } else {
                set_status(filename.substr(path.length + 1), repo, "err");
            }
        }
    });
}

function restore_file(filename, sha, file_content) {
    if (filename == get_path() + "/README.md") {
        $("#readme_content").val(Base64.decode(file_content));
    }
}

function update_file(filename, sha) {
    var path = get_path();
    var content = "";
    var message = "";
    if (filename == path + "/README.md") {
        content = $("#readme_content").val();
        message = $("#readme_message").val();
        if (message === "") {
            message = default_comment;
        }
        message = message.replace(/\{state\}/g, "");
    } else if (filename == path + "/Question.md") {
        content = "# " + $(".question-title:first").children(":first").html() + "\n\n";
        content += "[Original Page](" + window.location.href + ")\n\n";
        content += toMarkdown($(".question-content:first").html());
        message = default_comment.replace(/\{state\}/g, "");
    } else {
        content = $("#code_content").val();
        message = $("#code_message").val();
        if (message === "") {
            message = default_comment;
        }
    }
    message = parse_comment(message);

    $.ajax({
        url: github_api + '/repos/' + user  + '/' + repo + '/contents/' + filename,
        type: 'put',
        dataType: 'json',
        async: true,
        data: JSON.stringify({
            message: message,
            content: Base64.encode(content),
            sha: sha
        }),
        beforeSend: function(request) {
            request.setRequestHeader("Authorization", "token " + token);
        },
        success: function() {
            set_status(filename.substr(path.length + 1), repo, "succ");
        },
        error: function() {
            set_status(filename.substr(path.length + 1), repo, "err");
        }
    });
}

function set_status(filename, repo, status) {
    var $obj = filename == "README.md" ? $("#readme_alert") : $("#commit_status");
    if (status == "succ") {
        $obj.html('Commit "' + filename + '" to repository "' + repo + '" successfully');
        $obj.css("color", "green");
        setTimeout(function() {
            $obj.html("");
        }, 10000);
    } else {
        $obj.html("Fail to commit " + filename);
        $obj.css("color", "red");
    }
}

function get_path() {
    return $(".question-title:first").children(":first").html().replace(/ /g, "-").replace(/\./g, "");
}

function get_filename() {
    var filename;
    filename = $("#filename").val();
    if (filename === "") {
        var ext = get_extension();
        filename = "solution" + ext;
    }
    return filename;
}

function get_extension() {
    var ext = postfix[$("select[name=lang]").val()];
    if (!ext) {
        ext = ".code";
    }
    return ext;
}

function get_state(button) {
    var state = "";
    if (button === "submit") {
        state = $("#result-state").html().replace(/(^\s*)|(\s*$)/g, "").toLocaleLowerCase();
    } else if (button === "run") {
        state = $("#result_state").html().replace(/(^\s*)|(\s*$)/g, "").toLocaleLowerCase();
    } else {
        return;
    }
    if (state === "" || state === "pending" || state === "judging" || state === "failed") {
        state = "";
    }
    return state;
}

function parse_comment(comment) {
    var title = $(".question-title:first").children(":first").html();
    var state = $("#result-state").html().replace(/(^\s*)|(\s*$)/g, "");
    return comment.replace(/\{title\}/g, title).replace(/\{state\}/g, state);
}

function upload_problem() {
    var problem = {};
    problem.title = $(".question-title:first").children(":first").html().replace(/^\d+\. */, "");
    problem.url = window.location.href;
    problem.content = Base64.encode($(".question-content:first").html());
    problem.difficulty = $(".total-submit:last strong").html();

    var companies = [];
    if ($("#company_tags").length > 0) {
        $("#company_tags").next().children().each(function() {
            companies.push($(this).html());
        });
    }

    var tags = [];
    if ($("#tags").length > 0) {
        //$(".hidebutton:eq(-2) a").each(function() {
        $("#tags").next().children().each(function () {
            tags.push($(this).html());
        });
    }

    var contributor = {};
    contributor.github = user;
    contributor.leetcode = $.trim($(".dropdown-toggle:last").text());
    contributor.version = chrome.runtime.getManifest().version;

    var data = {};
    data.problem = problem;
    data.md5 = md5(JSON.stringify(problem));
    data.companies = companies.sort();
    data.tags = tags.sort();
    //data.locked = false;
    data.contributor = contributor;
    data.create_time = new Date();

    $.ajax({
        url: "https://chrome-ext.luxiakun.com/leetcode-ext/problem",
        type: 'post',
        contentType: "application/json",
        dataType: 'json',
        async: true,
        data: JSON.stringify(data),
        success: function (jsonData) {
            // window.open('', '_self', '');
            // window.close();
        },
        error: function(err) {
            console.log(err);
        }
    });
}<commit_msg>upload similar problems<commit_after>/**
 * Created by binarylu on 3/18/16.
 */

var github_api = 'https://api.github.com';

var token = "";
var user = "";
var repo = "";
var commit_cond = "";
var default_comment = "";

var postfix = {
    c: ".c",
    cpp: ".cpp",
    java: ".java",
    python: ".py",
    csharp: ".cs",
    javascript: ".js",
    ruby: ".rb",
    swift: ".swift",
    golang: ".go",
    base: ".sh",
    mysql: ".sql"
};

$(function(){
    var reg = new RegExp('submissions');
    if (window.location.pathname.match(reg) !== null)
        return false;
    chrome.storage.sync.get({
        token: '',
        oauth_token: '',
        user: '',
        repo_name: '',
        commit: ["accepted", "time limit exceeded", "compile error", "runtime error"],
        comment: ''
    }, function(items) {
        if(chrome.runtime.lastError) {
            console.log(chrome.runtime.lastError.message);
            return;
        }
        token = items.oauth_token;
        user = items.user;
        repo = items.repo_name;
        commit_cond = items.commit;
        default_comment = items.comment;

        upload_problem();
        if (items.token !== '' && items.oauth_token === '') {
            var $bulletin = $("");
            $("code-button").after($bulletin);
            var content = "LeetCode Extension does not support personal access token any more, please go to option page to login with OAuth.";
            $("#bulletin").html(content);
            $("#bulletin").css("color", "red");
        }

        if (token && user && repo) {
            add_node();
            $("#readme_button").click(restore);
            // $("#commit_readme").click({from: "commit_readme"}, commit);
            // $("#commit_question").click({from: "commit_question"}, commit);
            document.getElementById("commit_readme").onclick=function(){commit("commit_readme");};
            document.getElementById("commit_question").onclick=function(){commit("commit_question");};
            // submit button
            $("#button1").click(function() {
                $("#commit_status").html("");
            });
            $("#filename").val(get_filename());
            $('select[name=lang]').change(function () {
                var ext = get_extension();
                var filename = get_filename();
                filename = filename.substring(0, filename.lastIndexOf(".")) + ext;
                $("#filename").val(filename);
            });
            // result of submit
            $("#result-state").bind("DOMSubtreeModified", function() {
                var state = get_state("submit");
                if (state !== "" && $.inArray(state, commit_cond) != -1) {
                    commit("");
                }
            });
        } else {
            console.log("token: " + token);
            console.log("user: " + token);
            console.log("repo: " + token);
        }
    });
});

function add_node() {
    var $buttons = $("" +
        "<button type='button' class='btn btn-success' id='commit_question'>Add Question</button> " +
        "<button type='button' class='btn btn-success' data-toggle='modal' data-target='#readme' id='readme_button'>Add 'README.md'</button>" +
        "");
    var $div = $('' +
        '
' +
            '<form class="form-inline">' +
                '
' +
                    '
' +
                        '
' +
                            '' +
                                'Filename	' +
                            '' +
                                '<input type="text" class="form-control" id="filename" placeholder="Filename">	' +
                            '' +
                                'Comment	' +
                            '' +
                                '<input style="width:100%" type="text" class="form-control" id="code_message" placeholder="Input the comment for git commits">	' +
                        '
' +
                    '
' +
                '
' +
            '</form>' +
        '
');
    var $modal = $('' +
        '
' +
            '
' +
                '
' +
                    '
' +
                        '<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>' +
                        '
README.md
' +
                    '
' +
                    '
' +
                        'The following content will be commit to your Github repository.' +
                        '<textarea id="readme_content" class="form-control" rows="10"></textarea>
' +
                        '<input id="readme_message" type="text" class="form-control" placeholder="Input comments for git commit">' +
                    '
' +
                    '
' +
                        '' +
                        '<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>' +
                        '<button type="button" class="btn btn-primary" id="commit_readme">Commit</button>' +
                    '
' +
                '
' +
            '
' +
        '
');
    var $code = $("" +
        "<textarea id='code_content' style='display:none'></textarea>");

    $("code-button").after($buttons);
    $("div.action").before($div);
    $("body").append($modal).append($code);
    $("#code_message").val(default_comment);

    /* Only by this, the variable in original page can be got.
    * Even using jQuery like before can not get the variable in original page */
    var script = document.createElement("script");
    script.innerHTML = "var lxk_editor = {};" +
        "$(function(){" +
            "$('.editor').attr('id', 'ace_editor_id');" +
            "lxk_editor = ace.edit('ace_editor_id');" +
            "get_code();" +
            "$('select[name=lang]').change(get_code);" +
            "$('#button0').click(get_code);" +
            "$('#button1').click(get_code);" +
        "});" +
        "function get_code() {" +
            "$('#code_content').val(lxk_editor.getValue());" +
        "}";
    document.body.appendChild(script);
}

function commit(from) {
    $("#commit_status").html("");
    var filename = "";
    if (from == "commit_readme") {
        filename = "README.md";
    } else if (from == "commit_question") {
        filename = "Question.md";
    } else {
        filename = get_filename();
    }
    filename = get_path() + "/" + filename;
    get_file(filename, update_file, update_file);
}

function restore() {
    var filename = "README.md";
    filename = get_path() + "/" + filename;
    get_file(filename, restore_file);
    $("#readme_message").val(default_comment);
}

function get_file(filename, fsucc, ferr) {
    $.ajax({
        url: github_api + '/repos/' + user  + '/' + repo + '/contents/' + filename,
        type: 'get',
        dataType: 'json',
        async: true,
        beforeSend: function(request) {
            request.setRequestHeader("Authorization", "token " + token);
        },
        success: function(jsonData) {
            if (typeof(jsonData)=='undefined' || !jsonData) jsonData = {};
            var sha = jsonData.sha;
            var file_content = jsonData.content;
            fsucc(filename, sha, file_content);
        },
        error: function(err) {
            if (err.status == 404) {
                if(typeof ferr === "function") {
                    ferr(filename);
                }
            } else {
                set_status(filename.substr(path.length + 1), repo, "err");
            }
        }
    });
}

function restore_file(filename, sha, file_content) {
    if (filename == get_path() + "/README.md") {
        $("#readme_content").val(Base64.decode(file_content));
    }
}

function update_file(filename, sha) {
    var path = get_path();
    var content = "";
    var message = "";
    if (filename == path + "/README.md") {
        content = $("#readme_content").val();
        message = $("#readme_message").val();
        if (message === "") {
            message = default_comment;
        }
        message = message.replace(/\{state\}/g, "");
    } else if (filename == path + "/Question.md") {
        content = "# " + $(".question-title:first").children(":first").html() + "\n\n";
        content += "[Original Page](" + window.location.href + ")\n\n";
        content += toMarkdown($(".question-content:first").html());
        message = default_comment.replace(/\{state\}/g, "");
    } else {
        content = $("#code_content").val();
        message = $("#code_message").val();
        if (message === "") {
            message = default_comment;
        }
    }
    message = parse_comment(message);

    $.ajax({
        url: github_api + '/repos/' + user  + '/' + repo + '/contents/' + filename,
        type: 'put',
        dataType: 'json',
        async: true,
        data: JSON.stringify({
            message: message,
            content: Base64.encode(content),
            sha: sha
        }),
        beforeSend: function(request) {
            request.setRequestHeader("Authorization", "token " + token);
        },
        success: function() {
            set_status(filename.substr(path.length + 1), repo, "succ");
        },
        error: function() {
            set_status(filename.substr(path.length + 1), repo, "err");
        }
    });
}

function set_status(filename, repo, status) {
    var $obj = filename == "README.md" ? $("#readme_alert") : $("#commit_status");
    if (status == "succ") {
        $obj.html('Commit "' + filename + '" to repository "' + repo + '" successfully');
        $obj.css("color", "green");
        setTimeout(function() {
            $obj.html("");
        }, 10000);
    } else {
        $obj.html("Fail to commit " + filename);
        $obj.css("color", "red");
    }
}

function get_path() {
    return $(".question-title:first").children(":first").html().replace(/ /g, "-").replace(/\./g, "");
}

function get_filename() {
    var filename;
    filename = $("#filename").val();
    if (filename === "") {
        var ext = get_extension();
        filename = "solution" + ext;
    }
    return filename;
}

function get_extension() {
    var ext = postfix[$("select[name=lang]").val()];
    if (!ext) {
        ext = ".code";
    }
    return ext;
}

function get_state(button) {
    var state = "";
    if (button === "submit") {
        state = $("#result-state").html().replace(/(^\s*)|(\s*$)/g, "").toLocaleLowerCase();
    } else if (button === "run") {
        state = $("#result_state").html().replace(/(^\s*)|(\s*$)/g, "").toLocaleLowerCase();
    } else {
        return;
    }
    if (state === "" || state === "pending" || state === "judging" || state === "failed") {
        state = "";
    }
    return state;
}

function parse_comment(comment) {
    var title = $(".question-title:first").children(":first").html();
    var state = $("#result-state").html().replace(/(^\s*)|(\s*$)/g, "");
    return comment.replace(/\{title\}/g, title).replace(/\{state\}/g, state);
}

function upload_problem() {
    var problem = {};
    problem.title = $(".question-title:first").children(":first").html().replace(/^\d+\. */, "");
    problem.url = window.location.href;
    problem.content = Base64.encode($(".question-content:first").html());
    problem.difficulty = $(".total-submit:last strong").html();

    var companies = [];
    if ($("#company_tags").length > 0) {
        $("#company_tags").next().children().each(function() {
            companies.push($(this).html());
        });
    }

    var tags = [];
    if ($("#tags").length > 0) {
        $("#tags").next().children().each(function () {
            tags.push($(this).html());
        });
    }

    var similarities = [];
    if ($("#similar").length > 0) {
        $("#similar").next().children().each(function () {
            similarities.push($(this).html());
        });
    }

    var contributor = {};
    contributor.github = user;
    contributor.leetcode = $.trim($(".dropdown-toggle:last").text());
    contributor.version = chrome.runtime.getManifest().version;

    var data = {};
    data.problem = problem;
    data.md5 = md5(JSON.stringify(problem));
    data.companies = companies.sort();
    data.tags = tags.sort();
    data.similarities = similarities.sort();
    //data.locked = false;
    data.contributor = contributor;
    data.create_time = new Date();

    $.ajax({
        url: "https://chrome-ext.luxiakun.com/leetcode-ext/problem",
        type: 'post',
        contentType: "application/json",
        dataType: 'json',
        async: true,
        data: JSON.stringify(data),
        success: function (jsonData) {
            // window.open('', '_self', '');
            // window.close();
        },
        error: function(err) {
            console.log(err);
        }
    });
}<|endoftext|>