<commit_before>// Copyright 2017 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.
'use strict';

const fs = require('fs');
const path = require('path');

const FRONTEND_PATH = path.resolve(__dirname, '..', 'front_end');

const manifestModules = [];
for (var config of ['inspector.json', 'devtools_app.json', 'js_app.json', 'node_app.json', 'shell.json', 'worker_app.json'])
  manifestModules.push(...require(path.resolve(FRONTEND_PATH, config)).modules);

const utils = require('./utils');

const gnPath = path.resolve(__dirname, '..', 'BUILD.gn');
const gnFile = fs.readFileSync(gnPath, 'utf-8');
const gnLines = gnFile.split('\n');

function main() {
  let errors = [
    ...checkNonAutostartNonRemoteModules(),
    ...checkAllDevToolsFiles(),
    ...checkAllDevToolsModules(),
    ...checkCopiedDevToolsModules(),
  ];
  if (errors.length) {
    console.log('DevTools BUILD.gn checker detected errors!');
    console.log(`There's an issue with: ${gnPath}`);
    console.log(errors.join('\n'));
    process.exit(1);
  }
  console.log('DevTools BUILD.gn checker passed');
}

main();

/**
 * Ensures that generated module files are in the right list in BUILD.gn.
 * This is primarily to avoid remote modules from accidentally getting
 * bundled with the main Chrome binary.
 */
function checkNonAutostartNonRemoteModules() {
  const errors = [];
  const gnVariable = 'generated_non_autostart_non_remote_modules';
  const lines = selectGNLines(`${gnVariable} = [`, ']');
  if (!lines.length) {
    return [
      'Could not identify non-autostart non-remote modules in gn file',
      'Please look at: ' + __filename,
    ];
  }
  const text = lines.join('\n');
  const modules = manifestModules.filter(m => m.type !== 'autostart' && m.type !== 'remote').map(m => m.name);

  const missingModules = modules.filter(m => !utils.includes(text, `${m}/${m}_module.js`));
  if (missingModules.length)
    errors.push(`Check that you've included [${missingModules.join(', ')}] modules in: ` + gnVariable);

  // e.g. "$resources_out_dir/audits/audits_module.js" => "audits"
  const mapLineToModuleName = line => line.split('/')[2].split('_module')[0];

  const extraneousModules = lines.map(mapLineToModuleName).filter(module => !utils.includes(modules, module));
  if (extraneousModules.length)
    errors.push(`Found extraneous modules [${extraneousModules.join(', ')}] in: ` + gnVariable);

  return errors;
}

/**
 * Ensures that all source files (according to the various module.json files) are
 * listed in BUILD.gn.
 */
function checkAllDevToolsFiles() {
  return checkGNVariable('all_devtools_files', (moduleJSON) => {
    const scripts = moduleJSON.scripts || [];
    const resources = moduleJSON.resources || [];
    return [
      'module.json',
      ...scripts,
      ...resources,
    ];
  });
}

function checkAllDevToolsModules() {
  return checkGNVariable('all_devtools_modules', (moduleJSON) => {
    return moduleJSON.modules || [];
  });
}

function checkCopiedDevToolsModules() {
  return checkGNVariable(
      'copied_devtools_modules',
      (moduleJSON) => {
        return moduleJSON.modules || [];
      },
      (moduleName) => (filename) => {
        const relativePath = path.normalize(`$resources_out_dir/${moduleName}/${filename}`);
        return `"${relativePath}",`;
      });
}

function checkGNVariable(gnVariable, obtainFiles, obtainRelativePath) {
  const errors = [];
  const excludedFiles =
      ['InspectorBackendCommands.js', 'SupportedCSSProperties.js', 'ARIAProperties.js', 'axe.js', 'formatter_worker/']
      .map(path.normalize);
  const lines = selectGNLines(`${gnVariable} = [`, ']').map(path.normalize);
  if (!lines.length) {
    return [
      `Could not identify ${gnVariable} list in gn file`,
      'Please look at: ' + __filename,
    ];
  }
  const gnFiles = new Set(lines);
  var moduleFiles = [];
  fs.readdirSync(FRONTEND_PATH).forEach(function(moduleName) {
    const moduleJSONPath = path.join(FRONTEND_PATH, moduleName, 'module.json');
    if (utils.isFile(moduleJSONPath)) {
      const moduleJSON = require(moduleJSONPath);
      const files = obtainFiles(moduleJSON)
                        .map(obtainRelativePath && obtainRelativePath(moduleName) || relativePathFromBuildGN)
                        .filter(file => excludedFiles.every(excludedFile => !file.includes(excludedFile)));
      moduleFiles = moduleFiles.concat(files);

      function relativePathFromBuildGN(filename) {
        const relativePath = path.normalize(`front_end/${moduleName}/${filename}`);
        return `"${relativePath}",`;
      }
    }
  });
  for (const file of moduleFiles) {
    if (!gnFiles.has(file))
      errors.push(`Missing file in BUILD.gn for ${gnVariable}: ` + file);
  }
  return errors;
}

function selectGNLines(startLine, endLine) {
  let lines = gnLines.map(line => line.trim());
  let startIndex = lines.indexOf(startLine);
  if (startIndex === -1)
    return [];
  let endIndex = lines.indexOf(endLine, startIndex);
  if (endIndex === -1)
    return [];
  return lines.slice(startIndex + 1, endIndex);
}
<commit_msg>Fix check for nested directories in check_gn<commit_after>// Copyright 2017 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.
'use strict';

const fs = require('fs');
const path = require('path');

const FRONTEND_PATH = path.resolve(__dirname, '..', 'front_end');

const manifestModules = [];
for (var config of ['inspector.json', 'devtools_app.json', 'js_app.json', 'node_app.json', 'shell.json', 'worker_app.json'])
  manifestModules.push(...require(path.resolve(FRONTEND_PATH, config)).modules);

const utils = require('./utils');

const gnPath = path.resolve(__dirname, '..', 'BUILD.gn');
const gnFile = fs.readFileSync(gnPath, 'utf-8');
const gnLines = gnFile.split('\n');

function main() {
  let errors = [
    ...checkNonAutostartNonRemoteModules(),
    ...checkAllDevToolsFiles(),
    ...checkAllDevToolsModules(),
    ...checkCopiedDevToolsModules(),
  ];
  if (errors.length) {
    console.log('DevTools BUILD.gn checker detected errors!');
    console.log(`There's an issue with: ${gnPath}`);
    console.log(errors.join('\n'));
    process.exit(1);
  }
  console.log('DevTools BUILD.gn checker passed');
}

main();

/**
 * Ensures that generated module files are in the right list in BUILD.gn.
 * This is primarily to avoid remote modules from accidentally getting
 * bundled with the main Chrome binary.
 */
function checkNonAutostartNonRemoteModules() {
  const errors = [];
  const gnVariable = 'generated_non_autostart_non_remote_modules';
  const lines = selectGNLines(`${gnVariable} = [`, ']');
  if (!lines.length) {
    return [
      'Could not identify non-autostart non-remote modules in gn file',
      'Please look at: ' + __filename,
    ];
  }
  const text = lines.join('\n');
  const modules = manifestModules.filter(m => m.type !== 'autostart' && m.type !== 'remote').map(m => m.name);

  const missingModules = modules.filter(m => !utils.includes(text, `${m}/${m}_module.js`));
  if (missingModules.length)
    errors.push(`Check that you've included [${missingModules.join(', ')}] modules in: ` + gnVariable);

  // e.g. "$resources_out_dir/audits/audits_module.js" => "audits"
  const mapLineToModuleName = line => line.split('/')[2].split('_module')[0];

  const extraneousModules = lines.map(mapLineToModuleName).filter(module => !utils.includes(modules, module));
  if (extraneousModules.length)
    errors.push(`Found extraneous modules [${extraneousModules.join(', ')}] in: ` + gnVariable);

  return errors;
}

/**
 * Ensures that all source files (according to the various module.json files) are
 * listed in BUILD.gn.
 */
function checkAllDevToolsFiles() {
  return checkGNVariable('all_devtools_files', (moduleJSON) => {
    const scripts = moduleJSON.scripts || [];
    const resources = moduleJSON.resources || [];
    return [
      'module.json',
      ...scripts,
      ...resources,
    ];
  });
}

function checkAllDevToolsModules() {
  return checkGNVariable('all_devtools_modules', (moduleJSON) => {
    return moduleJSON.modules || [];
  });
}

function checkCopiedDevToolsModules() {
  return checkGNVariable(
      'copied_devtools_modules',
      (moduleJSON) => {
        return moduleJSON.modules || [];
      },
      (buildGNPath) => (filename) => {
        const relativePath = path.normalize(`$resources_out_dir/${buildGNPath}/${filename}`);
        return `"${relativePath}",`;
      });
}

function checkGNVariable(gnVariable, obtainFiles, obtainRelativePath) {
  const errors = [];
  const excludedFiles =
      ['InspectorBackendCommands.js', 'SupportedCSSProperties.js', 'ARIAProperties.js', 'axe.js', 'formatter_worker/']
      .map(path.normalize);
  const lines = selectGNLines(`${gnVariable} = [`, ']').map(path.normalize);
  if (!lines.length) {
    return [
      `Could not identify ${gnVariable} list in gn file`,
      'Please look at: ' + __filename,
    ];
  }
  const gnFiles = new Set(lines);
  var moduleFiles = [];

  function addModuleFilesForDirectory(moduleJSONPath, buildGNPath) {
    const moduleJSON = require(moduleJSONPath);
    const files = obtainFiles(moduleJSON)
                      .map(obtainRelativePath && obtainRelativePath(buildGNPath) || relativePathFromBuildGN)
                      .filter(file => excludedFiles.every(excludedFile => !file.includes(excludedFile)));
    moduleFiles = moduleFiles.concat(files);

    function relativePathFromBuildGN(filename) {
      const relativePath = path.normalize(`front_end/${buildGNPath}/${filename}`);
      return `"${relativePath}",`;
    }
  }

  function traverseDirectoriesForModuleJSONFiles(folderName, buildGNPath) {
    if (!fs.lstatSync(folderName).isDirectory()) {
      return;
    }
    const moduleJSONPath = path.join(folderName, 'module.json');
    if (utils.isFile(moduleJSONPath)) {
      addModuleFilesForDirectory(moduleJSONPath, buildGNPath);
    }

    fs.readdirSync(folderName).forEach((nestedModuleName) => {
      traverseDirectoriesForModuleJSONFiles(
          path.join(folderName, nestedModuleName), `${buildGNPath}/${nestedModuleName}`);
    });
  }

  fs.readdirSync(FRONTEND_PATH).forEach((moduleName) => {
    traverseDirectoriesForModuleJSONFiles(path.join(FRONTEND_PATH, moduleName), moduleName);
  });

  for (const file of moduleFiles) {
    if (!gnFiles.has(file))
      errors.push(`Missing file in BUILD.gn for ${gnVariable}: ` + file);
  }

  return errors;
}

function selectGNLines(startLine, endLine) {
  let lines = gnLines.map(line => line.trim());
  let startIndex = lines.indexOf(startLine);
  if (startIndex === -1)
    return [];
  let endIndex = lines.indexOf(endLine, startIndex);
  if (endIndex === -1)
    return [];
  return lines.slice(startIndex + 1, endIndex);
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const MinifyPlugin = require('babel-minify-webpack-plugin');
// const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
require('babel-polyfill');
require('whatwg-fetch');

const extractSass = new ExtractTextPlugin({
  filename: '../style/screen.css'
});

module.exports = (env) => {
  // set plugins - uncomment BrowserSyncPlugin and update host/ proxy values to enable browser-sync
  const plugins = [
    extractSass,
    // new BrowserSyncPlugin({
    //   open: 'external',
    //   host: 'example.test',
    //   port: 9000,
    //   proxy: 'http://example.test:8080/'
    // })
  ];

  if (env.NODE_ENV === 'prod') {
    plugins.push(
      new MinifyPlugin()
    );
  }

  return {
    entry: [
      'babel-polyfill',
      'whatwg-fetch',
      './public/content/themes/gj-boilerplate/js/src/scripts.js',
      './public/content/themes/gj-boilerplate/style/sass/screen.scss'
    ],
    output: {
      filename: 'main.js',
      path: path.resolve(__dirname, 'public/content/themes/gj-boilerplate/js')
    },
    externals: {
      jquery: 'jQuery'
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: {
            presets: ['env']
          }
        },
        {
          test: /\.scss$/,
          loader: extractSass.extract([
            {
              loader: 'css-loader',
              options: {
                minimize: env.NODE_ENV === 'prod'
              }
            },
            'postcss-loader',
            'sass-loader'
          ])
        }
      ]
    },
    plugins: plugins
  }
};<commit_msg>updates NODE_ENV<commit_after>'use strict';

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const MinifyPlugin = require('babel-minify-webpack-plugin');
// const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
require('babel-polyfill');
require('whatwg-fetch');

const extractSass = new ExtractTextPlugin({
  filename: '../style/screen.css'
});

module.exports = (env) => {
  // set plugins - uncomment BrowserSyncPlugin and update host/ proxy values to enable browser-sync
  const plugins = [
    extractSass,
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(env.NODE_ENV)
      }
    })
    // new BrowserSyncPlugin({
    //   open: 'external',
    //   host: 'example.test',
    //   port: 9000,
    //   proxy: 'http://example.test:8080/'
    // })
  ];

  if (env.NODE_ENV === 'prod') {
    plugins.push(
      new MinifyPlugin()
    );
  }

  return {
    entry: [
      'babel-polyfill',
      'whatwg-fetch',
      './public/content/themes/gj-boilerplate/js/src/scripts.js',
      './public/content/themes/gj-boilerplate/style/sass/screen.scss'
    ],
    output: {
      filename: 'main.js',
      path: path.resolve(__dirname, 'public/content/themes/gj-boilerplate/js')
    },
    externals: {
      jquery: 'jQuery'
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: {
            presets: ['env']
          }
        },
        {
          test: /\.scss$/,
          loader: extractSass.extract([
            {
              loader: 'css-loader',
              options: {
                minimize: env.NODE_ENV === 'prod'
              }
            },
            'postcss-loader',
            'sass-loader'
          ])
        }
      ]
    },
    plugins: plugins
  }
};
<|endoftext|>


<commit_before><commit_msg>compile jsx<commit_after><|endoftext|>


<commit_before><commit_msg>webpack config for file loader.<commit_after><|endoftext|>


<commit_before>/*********************************************
Script file for GradeVisualizer.

This script contains functionality that will make GradeVisualizer able
to calculate a user's grades, as well as add/remove assignments, and
load/save their grades to the server.

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

function main() {
  // Setup for facebook integration
  initFacebook();

  $('input[type=text]').change(updatePrediction);
  updatePrediction();
  $('.add-assignment').click(addNewAssignmentEvent);
  $('.remove-assignment').click(removeAssignment);

  $('.save-grades').click(saveGrades);
  $('.save-new-grades').click(saveGradesNew);
  $('.load-grades').click(loadGradesEvent);

  // Add some default assignments
  addNewAssignment("Homework 1");
  addNewAssignment("Homework 2");
  addNewAssignment("Homework 3");
  addNewAssignment("Midterm 1");
  addNewAssignment("Midterm 2");
  addNewAssignment("Final");
}

/*********************************************
Constants
*********************************************/
var SCORE = {
  EARNED: "earned",
  PROGRESS: "progress",
  LOST: "lost",
};

var SCORE_ROW = {
  NAME: 0,
  WEIGHT: 1,
  SCORE: 2,
};

/*********************************************
Global Definitions
*********************************************/
var g_nextAssignmentId = 0;

/*********************************************
Function/Object Definitions
*********************************************/

// Data structure used to hold Assignment data.
function Assignment(name, weight, score, id) {
  this.name = name;
  this.weight = weight;
  this.score = score;
  this.id = id;
  return this;
};

function calculateScores(assignments) {
  var scores = {};
  scores[SCORE.EARNED] = 0;
  scores[SCORE.PROGRESS] = 0;
  scores[SCORE.LOST] = 0;

  for (var i in assignments) {
    var assignment = assignments[i];
    var earned = assignment.weight * assignment.score / 100;
    // Ignore if user didn't specify weight
    if (assignment.weight !== null) {
      if (assignment.score !== null) {
        scores[SCORE.EARNED] += earned;
        scores[SCORE.LOST] += assignment.weight - earned;
      }
    }
  }
  scores[SCORE.PROGRESS] = (100 - scores[SCORE.EARNED]
    - scores[SCORE.LOST]);
  return scores;
}

function getAssignments(scoreTable) {
  var assignments = [];
  scoreTable.find('tr').each(function() {
    var inputs = $(this).find('input[type=text]');
    if (inputs.length && !$(this).hasClass('template')) {
      var weight = $(inputs[SCORE_ROW.WEIGHT]).val();
      weight = weight ? parseFloat(weight) : null;
      var score = $(inputs[SCORE_ROW.SCORE]).val();
      score = score ? parseFloat(score) : null;
      var id = $(this).find('.assignment-id').html();
      id = id ? parseInt(id) : null;
      assignments.push(new Assignment($(inputs[SCORE_ROW.NAME]).val(), weight,
        score, id));
    }
  });
  return assignments;
}

function scoreToGradeLetter(score) {
  if (score >= 90) {
    return 'A';
  } else if (score >= 80) {
    return 'B';
  } else if (score >= 70) {
    return 'C';
  } else if (score >= 60) {
    return 'D';
  }
  return 'F';
}

function displayPrediction(scores, predictionDiv) {
  // Update the progressbar to display the current values.
  for (var type in scores) {
    var bar = predictionDiv.find('.progress-bar.'+type);
    bar.html(
      // Fixed to 1 decimal point to not overwhelm the user with
      // unnecessary data.
      scores[type].toFixed(1))
      .css('display', (scores[type] > 0) ? 'block' : 'none')
      .css('width', scores[type]+'%');
  }

  // Update the letter grades
  // Expected score is a linear extrapolation of the student's past
  // performance. We take their average performance and expand it to
  // a scale of 100%.
  predictionDiv.find('.expected-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED] / (scores[SCORE.EARNED] + scores[SCORE.LOST]) * 100));
  // Maximum score assumes the student gets 100% on remaining
  // assignments.
  predictionDiv.find('.maximum-score').html(scoreToGradeLetter(
    100 - scores[SCORE.LOST]));
  // Median score assumes the student gets 50% on remaining assignments.
  predictionDiv.find('.median-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED] + 0.5 * scores[SCORE.PROGRESS]));
  // Minimum score assumes the student gets 0% on remaining assignments.
  predictionDiv.find('.minimum-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED]));
}

function saveGrades() {
  var classname = $('.class-name').val();
  var classidstr = $('.class-id').html();
  // When classidstr is not yet set, the DOM will have it set to "".
  // Trying to parseInt will give NaN and break the backend.
  var classid = (classidstr) ? parseInt(classidstr) : null;
  var assignments = getAssignments($('table.score'));
  $.ajax({
    type: 'POST',
    url: './save/',
    data: {
      classname: classname,
      classid: classid,
      assignments: assignments,
    }
  }).success(function(data, status, jqXHR) {
    // The server will return to us a class id.
    var classid = parseInt(data);
    $('.current.class-id').html(classid);

    // Update the load-grade entry with the new name
    var load_grade_links = $('.load-grades .class-id');
    for (var i = 0; i < load_grade_links.length; ++i) {
      var grade_link = $(load_grade_links[i]);
      if (parseInt(grade_link.html()) == classid) {
        grade_link.parent().find('.class-name').html(classname);
        break;
      }
    }
  });
}

function saveGradesNew() {
  var classidstr = $('.class-id').html("");
  saveGrades();
}

// This is called by facebook when their SDK is fully loaded.
function initFacebook() {
  (function (d){
    var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
    if (d.getElementById(id)) {return;}
    js = d.createElement('script'); js.id = id; js.async = true;
    js.src = "//connect.facebook.net/en_US/all.js";
    ref.parentNode.insertBefore(js, ref);
  }(document));

  // Here we run a very simple test of the Graph API after login is successful.
  // This testAPI() function is only called in those cases.
  function testAPI() {
    FB.api('/me', function(response) {
      showClasses(response.id);
    });
  }

  window.fbAsyncInit = function() {
    FB.init({
      appId      : '189336231272827',
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });

    // Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
    // for any authentication related change, such as login, logout or session refresh. This means that
    // whenever someone who was previously logged out tries to log in again, the correct case below
    // will be handled.
    FB.Event.subscribe('auth.authResponseChange', function(response) {
      // Here we specify what we do with the response anytime this event occurs.
      if (response.status === 'connected') {
        // The response object is returned with a status field that lets the app know the current
        // login status of the person. In this case, we're handling the situation where they
        // have logged in to the app.
        testAPI();
      } else if (response.status === 'not_authorized') {
        // In this case, the person is logged into Facebook, but not into the app, so we call
        // FB.login() to prompt them to do so.
        // In real-life usage, you wouldn't want to immediately prompt someone to login
        // like this, for two reasons:
        // (1) JavaScript created popup windows are blocked by most browsers unless they
        // result from direct interaction from people using the app (such as a mouse click)
        // (2) it is a bad experience to be continually prompted to login upon page load.
        FB.login();
      } else {
        // In this case, the person is not logged into Facebook, so we call the login()
        // function to prompt them to do so. Note that at this stage there is no indication
        // of whether they are logged into the app. If they aren't then they'll see the Login
        // dialog right after they log in to Facebook.
        // The same caveats as above apply to the FB.login() call here.
        FB.login();
      }
    });
  };
}

function loadGradesEvent() {
  var classid = parseInt($(this).find('.class-id').html());
  if (!isNaN(classid)) {
    loadGrades(classid);
  }
  return false;
}

function loadGrades(classid) {
  $.ajax({
    url: './load/',
    dataType: 'json',
    data: {
      classid: classid,
    }
  }).success(function(data, status, jqXHR) {
    var classname = data['classname'];
    var assignments = data['assignments'];

    $('.current.class-name').val(classname);
    $('.current.class-id').html(classid);
    $('tr:not(.template) td .remove-assignment').click();
    for (var i in assignments) {
      var assignment = assignments[i];
      addNewAssignment(assignment.name, assignment.weight, assignment.score, assignment.id);
    }
  });
}

function showClasses(u_id) {
  $.ajax({
    url: './classes/',
    dataType: 'json',
    data: {
      u_id: u_id
    }
  }).success(function(classes, status, jqXHR) {
    var classlist = $('.class-list');
    $('li.load-grades:not(.template)').remove();

    for (var i in classes) {
      var classLink = $('.load-grades.template').clone();
      classLink.find('.class-name').html(classes[i].name.length ? classes[i].name : "Untitled");
      classLink.find('.class-id').html(classes[i].id);
      classLink.removeClass('template');
      classLink.click(loadGradesEvent);
      classlist.append(classLink);
    }

    if (classes.length == 0) {
      var classLink = $('.load-grades.template').clone();
      classLink.find('.class-name').html("No classes found! Save a class to populate this list.");
      classLink.removeClass('template')
        .addClass('disabled')
        .click(loadGradesEvent);
      classlist.append(classLink);
    }
  })
}

// Wrapper around addNewAssignmentEvent so that the jQuery click
// event object isn't passed onto addNewAssignment.
function addNewAssignmentEvent() {
  addNewAssignment();
}

function addNewAssignment(name, weight, score, id) {
  // The template exists in the HTML file, so that we don't have to
  // build the assignment row from scratch. This is more readable!
  var assignmentRow = $('tr.template').clone();
  assignmentRow.removeClass('template');

  var inputs = assignmentRow.find('input[type=text]');
  inputs.change(updatePrediction);

  $(inputs.get(0)).val(name);
  $(inputs.get(1)).val(weight);
  $(inputs.get(2)).val(score);

  if (id === undefined || id === null || id == "") {
    id = g_nextAssignmentId++;
  }
  assignmentRow.find('.assignment-id').html(id);

  assignmentRow.find('.remove-assignment').click(removeAssignment);

  // The last child of the table body is the "Add new Assignment"
  // button, and we definitely want the assignment to come before
  // that.
  $('table.score tbody tr:last-child').before(assignmentRow);

  // The user probably wants to start changing the assignment details
  // if name wasn't specified
  if (!name || !name.length) {
    assignmentRow.find('td:first-child input[type=text]').focus();
  }
}

function updatePrediction() {
  var assignments = getAssignments($('table.score'));
  var scores = calculateScores(assignments);
  displayPrediction(scores, $(".prediction"));
}

// Event handler to remove an assignment row from its owning table.
function removeAssignment() {
  // Go up the DOM tree to find the table row
  // table -> tbody -> tr -> td -> input(remove button)
  $(this).parent().parent().remove();
  updatePrediction();
}

$(main)<commit_msg>Make default list of classes be empty<commit_after>/*********************************************
Script file for GradeVisualizer.

This script contains functionality that will make GradeVisualizer able
to calculate a user's grades, as well as add/remove assignments, and
load/save their grades to the server.

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

function main() {
  // Setup for facebook integration
  initFacebook();

  $('input[type=text]').change(updatePrediction);
  updatePrediction();
  $('.add-assignment').click(addNewAssignmentEvent);
  $('.remove-assignment').click(removeAssignment);

  $('.save-grades').click(saveGrades);
  $('.save-new-grades').click(saveGradesNew);
  $('.load-grades').click(loadGradesEvent);

  showClasses([]);

  // Add some default assignments
  addNewAssignment("Homework 1");
  addNewAssignment("Homework 2");
  addNewAssignment("Homework 3");
  addNewAssignment("Midterm 1");
  addNewAssignment("Midterm 2");
  addNewAssignment("Final");
}

/*********************************************
Constants
*********************************************/
var SCORE = {
  EARNED: "earned",
  PROGRESS: "progress",
  LOST: "lost",
};

var SCORE_ROW = {
  NAME: 0,
  WEIGHT: 1,
  SCORE: 2,
};

/*********************************************
Global Definitions
*********************************************/
var g_nextAssignmentId = 0;

/*********************************************
Function/Object Definitions
*********************************************/

// Data structure used to hold Assignment data.
function Assignment(name, weight, score, id) {
  this.name = name;
  this.weight = weight;
  this.score = score;
  this.id = id;
  return this;
};

function calculateScores(assignments) {
  var scores = {};
  scores[SCORE.EARNED] = 0;
  scores[SCORE.PROGRESS] = 0;
  scores[SCORE.LOST] = 0;

  for (var i in assignments) {
    var assignment = assignments[i];
    var earned = assignment.weight * assignment.score / 100;
    // Ignore if user didn't specify weight
    if (assignment.weight !== null) {
      if (assignment.score !== null) {
        scores[SCORE.EARNED] += earned;
        scores[SCORE.LOST] += assignment.weight - earned;
      }
    }
  }
  scores[SCORE.PROGRESS] = (100 - scores[SCORE.EARNED]
    - scores[SCORE.LOST]);
  return scores;
}

function getAssignments(scoreTable) {
  var assignments = [];
  scoreTable.find('tr').each(function() {
    var inputs = $(this).find('input[type=text]');
    if (inputs.length && !$(this).hasClass('template')) {
      var weight = $(inputs[SCORE_ROW.WEIGHT]).val();
      weight = weight ? parseFloat(weight) : null;
      var score = $(inputs[SCORE_ROW.SCORE]).val();
      score = score ? parseFloat(score) : null;
      var id = $(this).find('.assignment-id').html();
      id = id ? parseInt(id) : null;
      assignments.push(new Assignment($(inputs[SCORE_ROW.NAME]).val(), weight,
        score, id));
    }
  });
  return assignments;
}

function scoreToGradeLetter(score) {
  if (score >= 90) {
    return 'A';
  } else if (score >= 80) {
    return 'B';
  } else if (score >= 70) {
    return 'C';
  } else if (score >= 60) {
    return 'D';
  }
  return 'F';
}

function displayPrediction(scores, predictionDiv) {
  // Update the progressbar to display the current values.
  for (var type in scores) {
    var bar = predictionDiv.find('.progress-bar.'+type);
    bar.html(
      // Fixed to 1 decimal point to not overwhelm the user with
      // unnecessary data.
      scores[type].toFixed(1))
      .css('display', (scores[type] > 0) ? 'block' : 'none')
      .css('width', scores[type]+'%');
  }

  // Update the letter grades
  // Expected score is a linear extrapolation of the student's past
  // performance. We take their average performance and expand it to
  // a scale of 100%.
  predictionDiv.find('.expected-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED] / (scores[SCORE.EARNED] + scores[SCORE.LOST]) * 100));
  // Maximum score assumes the student gets 100% on remaining
  // assignments.
  predictionDiv.find('.maximum-score').html(scoreToGradeLetter(
    100 - scores[SCORE.LOST]));
  // Median score assumes the student gets 50% on remaining assignments.
  predictionDiv.find('.median-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED] + 0.5 * scores[SCORE.PROGRESS]));
  // Minimum score assumes the student gets 0% on remaining assignments.
  predictionDiv.find('.minimum-score').html(scoreToGradeLetter(
    scores[SCORE.EARNED]));
}

function saveGrades() {
  var classname = $('.class-name').val();
  var classidstr = $('.class-id').html();
  // When classidstr is not yet set, the DOM will have it set to "".
  // Trying to parseInt will give NaN and break the backend.
  var classid = (classidstr) ? parseInt(classidstr) : null;
  var assignments = getAssignments($('table.score'));
  $.ajax({
    type: 'POST',
    url: './save/',
    data: {
      classname: classname,
      classid: classid,
      assignments: assignments,
    }
  }).success(function(data, status, jqXHR) {
    // The server will return to us a class id.
    var classid = parseInt(data);
    $('.current.class-id').html(classid);

    // Update the load-grade entry with the new name
    var load_grade_links = $('.load-grades .class-id');
    for (var i = 0; i < load_grade_links.length; ++i) {
      var grade_link = $(load_grade_links[i]);
      if (parseInt(grade_link.html()) == classid) {
        grade_link.parent().find('.class-name').html(classname);
        break;
      }
    }
  });
}

function saveGradesNew() {
  var classidstr = $('.class-id').html("");
  saveGrades();
}

// This is called by facebook when their SDK is fully loaded.
function initFacebook() {
  (function (d){
    var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
    if (d.getElementById(id)) {return;}
    js = d.createElement('script'); js.id = id; js.async = true;
    js.src = "//connect.facebook.net/en_US/all.js";
    ref.parentNode.insertBefore(js, ref);
  }(document));

  // Here we run a very simple test of the Graph API after login is successful.
  // This testAPI() function is only called in those cases.
  function testAPI() {
    FB.api('/me', function(response) {
      updateClassesList(response.id);
    });
  }

  window.fbAsyncInit = function() {
    FB.init({
      appId      : '189336231272827',
      status     : true, // check login status
      cookie     : true, // enable cookies to allow the server to access the session
      xfbml      : true  // parse XFBML
    });

    // Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
    // for any authentication related change, such as login, logout or session refresh. This means that
    // whenever someone who was previously logged out tries to log in again, the correct case below
    // will be handled.
    FB.Event.subscribe('auth.authResponseChange', function(response) {
      // Here we specify what we do with the response anytime this event occurs.
      if (response.status === 'connected') {
        // The response object is returned with a status field that lets the app know the current
        // login status of the person. In this case, we're handling the situation where they
        // have logged in to the app.
        testAPI();
      } else if (response.status === 'not_authorized') {
        // In this case, the person is logged into Facebook, but not into the app, so we call
        // FB.login() to prompt them to do so.
        // In real-life usage, you wouldn't want to immediately prompt someone to login
        // like this, for two reasons:
        // (1) JavaScript created popup windows are blocked by most browsers unless they
        // result from direct interaction from people using the app (such as a mouse click)
        // (2) it is a bad experience to be continually prompted to login upon page load.
        FB.login();
      } else {
        // In this case, the person is not logged into Facebook, so we call the login()
        // function to prompt them to do so. Note that at this stage there is no indication
        // of whether they are logged into the app. If they aren't then they'll see the Login
        // dialog right after they log in to Facebook.
        // The same caveats as above apply to the FB.login() call here.
        FB.login();
      }
    });
  };
}

function loadGradesEvent() {
  var classid = parseInt($(this).find('.class-id').html());
  if (!isNaN(classid)) {
    loadGrades(classid);
  }
  return false;
}

function loadGrades(classid) {
  $.ajax({
    url: './load/',
    dataType: 'json',
    data: {
      classid: classid,
    }
  }).success(function(data, status, jqXHR) {
    var classname = data['classname'];
    var assignments = data['assignments'];

    $('.current.class-name').val(classname);
    $('.current.class-id').html(classid);
    $('tr:not(.template) td .remove-assignment').click();
    for (var i in assignments) {
      var assignment = assignments[i];
      addNewAssignment(assignment.name, assignment.weight, assignment.score, assignment.id);
    }
  });
}

function updateClassesList(u_id) {
  $.ajax({
    url: './classes/',
    dataType: 'json',
    data: {
      u_id: u_id
    }
  }).success(function(classes, status, jqXHR) {
    showClasses(classes);
  })
}

function showClasses(classes) {
  var classlist = $('.class-list');
  $('li.load-grades:not(.template)').remove();

  for (var i in classes) {
    var classLink = $('.load-grades.template').clone();
    classLink.find('.class-name').html(classes[i].name.length ? classes[i].name : "Untitled");
    classLink.find('.class-id').html(classes[i].id);
    classLink.removeClass('template');
    classLink.click(loadGradesEvent);
    classlist.append(classLink);
  }

  if (classes.length == 0) {
    var classLink = $('.load-grades.template').clone();
    classLink.find('.class-name').html("No classes found! Save a class to populate this list.");
    classLink.removeClass('template')
      .addClass('disabled')
      .click(loadGradesEvent);
    classlist.append(classLink);
  }
}

// Wrapper around addNewAssignmentEvent so that the jQuery click
// event object isn't passed onto addNewAssignment.
function addNewAssignmentEvent() {
  addNewAssignment();
}

function addNewAssignment(name, weight, score, id) {
  // The template exists in the HTML file, so that we don't have to
  // build the assignment row from scratch. This is more readable!
  var assignmentRow = $('tr.template').clone();
  assignmentRow.removeClass('template');

  var inputs = assignmentRow.find('input[type=text]');
  inputs.change(updatePrediction);

  $(inputs.get(0)).val(name);
  $(inputs.get(1)).val(weight);
  $(inputs.get(2)).val(score);

  if (id === undefined || id === null || id == "") {
    id = g_nextAssignmentId++;
  }
  assignmentRow.find('.assignment-id').html(id);

  assignmentRow.find('.remove-assignment').click(removeAssignment);

  // The last child of the table body is the "Add new Assignment"
  // button, and we definitely want the assignment to come before
  // that.
  $('table.score tbody tr:last-child').before(assignmentRow);

  // The user probably wants to start changing the assignment details
  // if name wasn't specified
  if (!name || !name.length) {
    assignmentRow.find('td:first-child input[type=text]').focus();
  }
}

function updatePrediction() {
  var assignments = getAssignments($('table.score'));
  var scores = calculateScores(assignments);
  displayPrediction(scores, $(".prediction"));
}

// Event handler to remove an assignment row from its owning table.
function removeAssignment() {
  // Go up the DOM tree to find the table row
  // table -> tbody -> tr -> td -> input(remove button)
  $(this).parent().parent().remove();
  updatePrediction();
}

$(main)<|endoftext|>


<commit_before>// javascript:(function(){if(!window.__profiler__%20||%20window.__profiler__.scriptLoaded%20!==%20true)%20{var%20d=document,h=d.getElementsByTagName(%27head%27)[0],s=d.createElement(%27script%27),l=d.createElement(%27div%27),c=function(){if(l){d.body.removeChild(l)}},t=new%20Date();s.type=%27text/javascript%27;l.style.cssText=%27z-index:999;position:fixed;top:10px;left:10px;display:inline;width:auto;font-size:14px;line-height:1.5em;font-family:Helvetica,Calibri,Arial,sans-serif;text-shadow:none;padding:3px%2010px%200;background:#FFFDF2;box-shadow:0%200%200%203px%20rgba(0,0,0,.5),0%200%205px%20rgba(0,0,0,.5);%20border-radius:1px%27;l.innerHTML=%27Just%20a%20moment%27;s.src=%27http://chrisheilmann.s3.amazonaws.com/timing.js?%27+t.getTime();s.onload=c;s.onreadystatechange=function(){if(this.readyState==%27loaded%27){c()}};d.body.appendChild(l);h.appendChild(s);}%20else%20if(typeof%20window.__profiler__%20===%20%27function%27)%20{window.__profiler__();}})()
(function(){
	if(!window.__profiler__ || window.__profiler__.scriptLoaded !== true) {
		var d=document,
			h=d.getElementsByTagName('head')[0],
			s=d.createElement('script'),
			l=d.createElement('div'),
			c=function(){if(l){d.body.removeChild(l)}},
			t=new Date();
		s.type='text/javascript';
		l.style.cssText='z-index:999;position:fixed;top:10px;left:10px;display:inline;width:auto;font-size:14px;line-height:1.5em;font-family:Helvetica,Calibri,Arial,sans-serif;text-shadow:none;padding:3px 10px 0;background:#FFFDF2;box-shadow:0 0 0 3px rgba(0,0,0,.25),0 0 5px 5px rgba(0,0,0,.25); border-radius:1px';
		l.innerHTML='Just a moment';
		s.src='http://chrisheilmann.s3.amazonaws.com/timing.js?'+t.getTime();
		s.onload=c;
		s.onreadystatechange=function(){if(this.readyState=='loaded'){c()}};
		d.body.appendChild(l);
		h.appendChild(s);
	} else if(typeof window.__profiler__ === 'function') {window.__profiler__();}
})()<commit_msg>some changes :P<commit_after>// javascript:(function(){if(!window.__profiler__%20||%20window.__profiler__.scriptLoaded%20!==%20true)%20{var%20d=document,h=d.getElementsByTagName(%27head%27)[0],s=d.createElement(%27script%27),l=d.createElement(%27div%27),c=function(){if(l){d.body.removeChild(l)}},t=new%20Date();s.type=%27text/javascript%27;l.style.cssText=%27z-index:999;position:fixed;top:10px;left:10px;display:inline;width:auto;font-size:14px;line-height:1.5em;font-family:Helvetica,Calibri,Arial,sans-serif;text-shadow:none;padding:3px%2010px%200;background:#FFFDF2;box-shadow:0%200%200%203px%20rgba(0,0,0,.25),0%200%205px%205px%20rgba(0,0,0,.25);%20border-radius:1px%27;l.innerHTML=%27Just%20a%20moment%27;s.src=%27http://chrisheilmann.s3.amazonaws.com/timing.js?%27+t.getTime();s.onload=c;s.onreadystatechange=function(){if(this.readyState==%27loaded%27){c()}};d.body.appendChild(l);h.appendChild(s);}%20else%20if(typeof%20window.__profiler__%20===%20%27function%27)%20{window.__profiler__();}})()
(function(){
	if(!window.__profiler__ || window.__profiler__.scriptLoaded !== true) {
		var d=document,
			h=d.getElementsByTagName('head')[0],
			s=d.createElement('script'),
			l=d.createElement('div'),
			c=function(){if(l){d.body.removeChild(l)}},
			t=new Date();
		s.type='text/javascript';
		l.style.cssText='z-index:999;position:fixed;top:10px;left:10px;display:inline;width:auto;font-size:14px;line-height:1.5em;font-family:Helvetica,Calibri,Arial,sans-serif;text-shadow:none;padding:3px 10px 0;background:#FFFDF2;box-shadow:0 0 0 3px rgba(0,0,0,.25),0 0 5px 5px rgba(0,0,0,.25); border-radius:1px';
		l.innerHTML='Just a moment';
		s.src='http://chrisheilmann.s3.amazonaws.com/timing.js?'+t.getTime();
		s.onload=c;
		s.onreadystatechange=function(){if(this.readyState=='loaded'){c()}};
		d.body.appendChild(l);
		h.appendChild(s);
	} else if(typeof window.__profiler__ === 'function') {window.__profiler__();}
})()<|endoftext|>


<commit_before>(function() {
  var slice = Array.prototype.slice;

  function update(array, args) {
    var arrayLength = array.length, length = args.length;
    while (length--) array[arrayLength + length] = args[length];
    return array;
  };

  function merge(array, args) {
    array = slice.call(array, 0);
    return update(array, args);
  };

  Function.prototype.bind = function(context) {
    if (arguments.length < 2 && typeof arguments[0] === 'undefined') {
      return this;
    }
    var __method = this;
    var args = slice.call(arguments, 1);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(context, a);
    }
  }

})();

function nblck_each(array, body, after) {
	$.each(array, function(i) {
		body(this, i);
	});

	after();
};

function nblck_map(array, func, after) {
	var acc = [];

	nblck_each(array, function(elem, index) {
		acc.push(func(elem, index));
	}, function(){
		after(acc);
	});
};

function ScriptletCenter()
{
    this.scriptlets = {};

    this.scriptlets['insert_text'] = function(context, params, text, move_forward, move_up, done)
    {
        done(params.text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['insert_tag'] = function(context, params, text, move_forward, move_up, done)
    {
        var padding_top = '';
        for (var i=params.padding_top; i; i--)
            padding_top += '\n';

        var start_tag = '<'+params.tag;
        var cursor_inside = false;

        for (var attr in params.attrs) {
            start_tag += ' '+attr+'="' + params.attrs[attr] + '"';
        }

        start_tag += '>';
        var end_tag = '</'+params.tag+'>';

        var padding_bottom = '';
        for (var i=params.padding_bottom; i; i--)
            padding_bottom += '\n';

        if(text.length > 0) {
            // tokenize
            var output = '';
            var token = '';
            for(var index=0; index < text.length; index++)
            {
                if (text[index].match(/\s/)) { // whitespace
                    token += text[index];
                }
                else { // character
                    output += token;
                    if(output == token) output += padding_top + start_tag;
                    token = '';
                    output += text[index];
                }
            }

            if( output[output.length-1] == '\\' ) {
                output = output.substr(0, output.length-1) + end_tag + padding_bottom + '\\';
            } else {
                output += end_tag + padding_bottom;
            }
            output += token;

            // keep cursor inside tag if some previous scriptlet has already moved it
            cursor_inside = move_forward != 0 || move_up != 0;
        }
        else {
            if(params.nocontent) {
                output = padding_top + "<"+params.tag +" />" + padding_bottom;
            }
            else {
                output = padding_top + start_tag + end_tag + padding_bottom;
                cursor_inside = true;
            }
        }

        if (cursor_inside) {
            move_forward -= params.tag.length + 3;
            move_up += params.padding_bottom || 0;
        }

        done(output, move_forward, move_up);
    }.bind(this);

    this.scriptlets['lineregexp'] = function(context, params, text, move_forward, move_up, done) {
		var self = this;

        var exprs = $.map(params.exprs, function(expr) {
            var opts = "g";
            if(expr.length > 2) {
                opts = expr[2];
            } return {
                rx: new RegExp(expr[0], opts),
                repl: expr[1]
                };
        });

        if(!text) done(text, move_forward, move_up);

        var changed = 0;
        var lines = text.split('\n');

		nblck_map(lines, function(line, index) {
            var old_line = line;
            $(exprs).each(function() {
                var expr = this;
                line = line.replace(expr.rx, expr.repl);
            });

			$progress.html(index);

            if(old_line != line) changed += 1;
            return line;
        }, function(newlines) {
            if(changed > 0) {
                text = newlines.join('\n');
            };

            done(text, move_forward, move_up);
		});
    }.bind(this);

    this.scriptlets['fulltextregexp'] = function(context, params, text, move_forward, move_up, done) {
		var self = this;

        var exprs = $.map(params.exprs, function(expr) {
            var opts = "mg";
            if(expr.length > 2) {
                opts = expr[2];
            }
            return {
                rx: new RegExp(expr[0], opts),
                repl: expr[1]
                };
        });

        if(!text) done(text, move_forward, move_up);

		nblck_each(exprs, function(expr, index) {
			$progress.html(600 + index);
            text = text.replace(expr.rx, expr.repl);
        }, function() {
			done(text, move_forward, move_up);
		});
    }.bind(this);

    this.scriptlets['macro'] = function(context, params, text, move_forward, move_up, done) {
        var self = this;
		var i = 0;

		function next(text, move_forward, move_up) {
        	if (i < params.length) {
				var e = params[i];
				i = i + 1;
				self.scriptlets[e[0]](context, e[1], text, move_forward, move_up, next);
			}
			else {
				done(text, move_forward, move_up);
			}
        };

		next(text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['lowercase'] = function(context, params, text, move_forward, move_up, done)
    {
        if(!text) done(text, move_forward, move_up);
        done(text.toLowerCase(), move_forward, move_up);
    }.bind(this);

    this.scriptlets["insert_stanza"] = function(context, params, text, move_forward, move_up, done) {
        var padding_top = '';
        for (var i=params.padding_top; i; i--)
            padding_top += '\n';

        var padding_bottom = '';
        for (var i=params.padding_bottom; i; i--)
            padding_bottom += '\n';

        if(text) {
            var verses = text.split('\n');
            text = ''; var buf = ''; var ebuf = '';
            var first = true;

            for(var i=0;  i < verses.length; i++) {
                var verse = verses[i].replace(/^\s+/, "").replace(/\s+$/, "");
                if(verse) {
                    text += (buf ? buf + '/\n' : '') + ebuf;
                    buf = (first ? '<strofa>\n' : '') + verses[i];
                    ebuf = '';
                    first = false;
                } else {
                    ebuf += '\n' + verses[i];
                }
            }
            text = padding_top + text + buf + '\n</strofa>' + padding_bottom + ebuf;
        }
        else {
            text = padding_top + "<strofa></strofa>" + padding_bottom;
            move_forward -= "</strofa>".length;
            move_up += params.padding_bottom || 0;
        }

        done(text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['autotag'] = function(context, params, text, move_forward, move_up, done)
    {
        if(!text.match(/^\n+$/)) done(text, move_forward, move_up);

        var output = '';

        function insert_done(text, mf, mu) {
            output += text;
        }

        if (!params.split) params.split = 2;
        if (!params.padding) params.padding = 3;

        if (params.tag == 'strofa')
            tagger = this.scriptlets['insert_stanza'];
        else
            tagger = this.scriptlets['insert_tag'];

        var padding_top = text.match(/^\n+/)
        output = padding_top ? padding_top[0] : '';

        padding = '';
        for(var i=params.padding; i; --i) {
            padding += "\n";
        }

        text = text.substr(output.length);
        var chunk_reg = new RegExp("^([\\s\\S]+?)(\\n{"+params.split+",}|$)");
        while (match = text.match(chunk_reg)) {
            if (params.tag == 'akap' && match[1].match(/^---/))
                tag = 'akap_dialog';
            else tag = params.tag;
            tagger(context, {tag: tag}, match[1], 0, 0, insert_done);
            if (match[2].length > params.padding)
                output += match[2];
            else
                output += padding;
            text = text.substr(match[0].length)
        }

        output += text;

        done(output, move_forward, move_up);
    }.bind(this);

    this.scriptlets['slugify'] = function(context, params, text, move_forward, move_up, done)
    {
        done(slugify(text.replace(/_/g, '-')), move_forward, move_up);
    }.bind(this);

}

ScriptletCenter.prototype.callInteractive = function(opts) {
	$progress = $('Executing script');
	var self = this;

	/* This won't work, 'cause the JS below might be synchronous :( */
	/* var timer = setTimeout(function() {
	    $.blockUI({message: $progress});
	    timer = null;
	}, 1000); */

	$.blockUI({message: $progress, showOverlay: false});

    var input = self.XMLEditorSelectedText(opts.context);
	self.scriptlets[opts.action](opts.context, opts.extra, input, 0, 0, function(output, move_forward, move_up){
	    /*if(timer)
	        clearTimeout(timer);
	    else */
        if (input != output) {
            self.XMLEditorReplaceSelectedText(opts.context, output)
        }
        if (move_forward || move_up) {
            try {
                self.XMLEditorMoveCursorForward(opts.context, move_forward, move_up)
            }
            catch(e) {}
        }
	    $.unblockUI(); // done
	});
}

ScriptletCenter.prototype.XMLEditorSelectedText = function(editor) {

    return editor.selection();
};

ScriptletCenter.prototype.XMLEditorReplaceSelectedText = function(editor, replacement)
{
	$progress.html("Replacing text");
	editor.replaceSelection(replacement);
};

ScriptletCenter.prototype.XMLEditorMoveCursorForward = function(panel, right, up) {
    var pos = panel.cursorPosition();
    if (up) {
        line = pos.line;
        while (up < 0) {
            line = panel.nextLine(line);
            ++up;
        }
        while (up > 0) {
            line = panel.prevLine(line);
            --up;
        }
        len = panel.lineContent(line).length;
        panel.selectLines(line, len + right);
    }
    else {
        panel.selectLines(pos.line, pos.character + right);
    }
};

var scriptletCenter;

$(function() {
    scriptletCenter = new ScriptletCenter();
});
<commit_msg>Prevent a race condition between "Replacing text" label and the save dialog, probably fixes #3484<commit_after>(function() {
  var slice = Array.prototype.slice;

  function update(array, args) {
    var arrayLength = array.length, length = args.length;
    while (length--) array[arrayLength + length] = args[length];
    return array;
  };

  function merge(array, args) {
    array = slice.call(array, 0);
    return update(array, args);
  };

  Function.prototype.bind = function(context) {
    if (arguments.length < 2 && typeof arguments[0] === 'undefined') {
      return this;
    }
    var __method = this;
    var args = slice.call(arguments, 1);
    return function() {
      var a = merge(args, arguments);
      return __method.apply(context, a);
    }
  }

})();

function nblck_each(array, body, after) {
	$.each(array, function(i) {
		body(this, i);
	});

	after();
};

function nblck_map(array, func, after) {
	var acc = [];

	nblck_each(array, function(elem, index) {
		acc.push(func(elem, index));
	}, function(){
		after(acc);
	});
};

function ScriptletCenter()
{
    this.scriptlets = {};

    this.scriptlets['insert_text'] = function(context, params, text, move_forward, move_up, done)
    {
        done(params.text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['insert_tag'] = function(context, params, text, move_forward, move_up, done)
    {
        var padding_top = '';
        for (var i=params.padding_top; i; i--)
            padding_top += '\n';

        var start_tag = '<'+params.tag;
        var cursor_inside = false;

        for (var attr in params.attrs) {
            start_tag += ' '+attr+'="' + params.attrs[attr] + '"';
        }

        start_tag += '>';
        var end_tag = '</'+params.tag+'>';

        var padding_bottom = '';
        for (var i=params.padding_bottom; i; i--)
            padding_bottom += '\n';

        if(text.length > 0) {
            // tokenize
            var output = '';
            var token = '';
            for(var index=0; index < text.length; index++)
            {
                if (text[index].match(/\s/)) { // whitespace
                    token += text[index];
                }
                else { // character
                    output += token;
                    if(output == token) output += padding_top + start_tag;
                    token = '';
                    output += text[index];
                }
            }

            if( output[output.length-1] == '\\' ) {
                output = output.substr(0, output.length-1) + end_tag + padding_bottom + '\\';
            } else {
                output += end_tag + padding_bottom;
            }
            output += token;

            // keep cursor inside tag if some previous scriptlet has already moved it
            cursor_inside = move_forward != 0 || move_up != 0;
        }
        else {
            if(params.nocontent) {
                output = padding_top + "<"+params.tag +" />" + padding_bottom;
            }
            else {
                output = padding_top + start_tag + end_tag + padding_bottom;
                cursor_inside = true;
            }
        }

        if (cursor_inside) {
            move_forward -= params.tag.length + 3;
            move_up += params.padding_bottom || 0;
        }

        done(output, move_forward, move_up);
    }.bind(this);

    this.scriptlets['lineregexp'] = function(context, params, text, move_forward, move_up, done) {
		var self = this;

        var exprs = $.map(params.exprs, function(expr) {
            var opts = "g";
            if(expr.length > 2) {
                opts = expr[2];
            } return {
                rx: new RegExp(expr[0], opts),
                repl: expr[1]
                };
        });

        if(!text) done(text, move_forward, move_up);

        var changed = 0;
        var lines = text.split('\n');

		nblck_map(lines, function(line, index) {
            var old_line = line;
            $(exprs).each(function() {
                var expr = this;
                line = line.replace(expr.rx, expr.repl);
            });

			$progress.html(index);

            if(old_line != line) changed += 1;
            return line;
        }, function(newlines) {
            if(changed > 0) {
                text = newlines.join('\n');
            };

            done(text, move_forward, move_up);
		});
    }.bind(this);

    this.scriptlets['fulltextregexp'] = function(context, params, text, move_forward, move_up, done) {
		var self = this;

        var exprs = $.map(params.exprs, function(expr) {
            var opts = "mg";
            if(expr.length > 2) {
                opts = expr[2];
            }
            return {
                rx: new RegExp(expr[0], opts),
                repl: expr[1]
                };
        });

        if(!text) done(text, move_forward, move_up);

		nblck_each(exprs, function(expr, index) {
			$progress.html(600 + index);
            text = text.replace(expr.rx, expr.repl);
        }, function() {
			done(text, move_forward, move_up);
		});
    }.bind(this);

    this.scriptlets['macro'] = function(context, params, text, move_forward, move_up, done) {
        var self = this;
		var i = 0;

		function next(text, move_forward, move_up) {
        	if (i < params.length) {
				var e = params[i];
				i = i + 1;
				self.scriptlets[e[0]](context, e[1], text, move_forward, move_up, next);
			}
			else {
				done(text, move_forward, move_up);
			}
        };

		next(text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['lowercase'] = function(context, params, text, move_forward, move_up, done)
    {
        if(!text) done(text, move_forward, move_up);
        done(text.toLowerCase(), move_forward, move_up);
    }.bind(this);

    this.scriptlets["insert_stanza"] = function(context, params, text, move_forward, move_up, done) {
        var padding_top = '';
        for (var i=params.padding_top; i; i--)
            padding_top += '\n';

        var padding_bottom = '';
        for (var i=params.padding_bottom; i; i--)
            padding_bottom += '\n';

        if(text) {
            var verses = text.split('\n');
            text = ''; var buf = ''; var ebuf = '';
            var first = true;

            for(var i=0;  i < verses.length; i++) {
                var verse = verses[i].replace(/^\s+/, "").replace(/\s+$/, "");
                if(verse) {
                    text += (buf ? buf + '/\n' : '') + ebuf;
                    buf = (first ? '<strofa>\n' : '') + verses[i];
                    ebuf = '';
                    first = false;
                } else {
                    ebuf += '\n' + verses[i];
                }
            }
            text = padding_top + text + buf + '\n</strofa>' + padding_bottom + ebuf;
        }
        else {
            text = padding_top + "<strofa></strofa>" + padding_bottom;
            move_forward -= "</strofa>".length;
            move_up += params.padding_bottom || 0;
        }

        done(text, move_forward, move_up);
    }.bind(this);

    this.scriptlets['autotag'] = function(context, params, text, move_forward, move_up, done)
    {
        if(!text.match(/^\n+$/)) done(text, move_forward, move_up);

        var output = '';

        function insert_done(text, mf, mu) {
            output += text;
        }

        if (!params.split) params.split = 2;
        if (!params.padding) params.padding = 3;

        if (params.tag == 'strofa')
            tagger = this.scriptlets['insert_stanza'];
        else
            tagger = this.scriptlets['insert_tag'];

        var padding_top = text.match(/^\n+/)
        output = padding_top ? padding_top[0] : '';

        padding = '';
        for(var i=params.padding; i; --i) {
            padding += "\n";
        }

        text = text.substr(output.length);
        var chunk_reg = new RegExp("^([\\s\\S]+?)(\\n{"+params.split+",}|$)");
        while (match = text.match(chunk_reg)) {
            if (params.tag == 'akap' && match[1].match(/^---/))
                tag = 'akap_dialog';
            else tag = params.tag;
            tagger(context, {tag: tag}, match[1], 0, 0, insert_done);
            if (match[2].length > params.padding)
                output += match[2];
            else
                output += padding;
            text = text.substr(match[0].length)
        }

        output += text;

        done(output, move_forward, move_up);
    }.bind(this);

    this.scriptlets['slugify'] = function(context, params, text, move_forward, move_up, done)
    {
        done(slugify(text.replace(/_/g, '-')), move_forward, move_up);
    }.bind(this);

}

ScriptletCenter.prototype.callInteractive = function(opts) {
	$progress = $('Executing script');
	var self = this;

	/* This won't work, 'cause the JS below might be synchronous :( */
	/* var timer = setTimeout(function() {
	    $.blockUI({message: $progress});
	    timer = null;
	}, 1000); */

	$.blockUI({message: $progress, showOverlay: false});

    $('#save-button').attr('disabled', true);
    var input = self.XMLEditorSelectedText(opts.context);
    window.setTimeout(function() {
        self.scriptlets[opts.action](opts.context, opts.extra, input, 0, 0, function(output, move_forward, move_up){
            /*if(timer)
                clearTimeout(timer);
            else */
            if (input != output) {
                self.XMLEditorReplaceSelectedText(opts.context, output)
            }
            if (move_forward || move_up) {
                try {
                    self.XMLEditorMoveCursorForward(opts.context, move_forward, move_up)
                }
                catch(e) {}
            }
            $.unblockUI({onUnblock: function() { $('#save-button').attr('disabled', null)}}); // done
        });
    }, 0);

}

ScriptletCenter.prototype.XMLEditorSelectedText = function(editor) {

    return editor.selection();
};

ScriptletCenter.prototype.XMLEditorReplaceSelectedText = function(editor, replacement)
{
	$progress.html("Replacing text");
	editor.replaceSelection(replacement);
};

ScriptletCenter.prototype.XMLEditorMoveCursorForward = function(panel, right, up) {
    var pos = panel.cursorPosition();
    if (up) {
        line = pos.line;
        while (up < 0) {
            line = panel.nextLine(line);
            ++up;
        }
        while (up > 0) {
            line = panel.prevLine(line);
            --up;
        }
        len = panel.lineContent(line).length;
        panel.selectLines(line, len + right);
    }
    else {
        panel.selectLines(pos.line, pos.character + right);
    }
};

var scriptletCenter;

$(function() {
    scriptletCenter = new ScriptletCenter();
});
<|endoftext|>


<commit_before>/*!
 * An implementation of Conway's Game of Life.
 *
 * Version: snapshot
 * <https://github.com/tkareine/game_of_life>
 *
 * Requires Underscore 1.1.6 or newer.
 *
 * Copyright (c) 2011 Tuomas Kareinen. Licensed under the MIT license.
 */(function(a){"use strict",window.GameOfLife=function(b,c){function g(b,c){return!a.isEqual(b,c)}var d=GameOfLife,e=d.Support.parseCellGrid(b),f=d.Graphics(d.Support.validateCanvas(c),e);return{evolve:function(){function c(){f.drawFrame(e,a),b=e,e=d.Generation.tick(b),g(b,e)&&(a+=1,setTimeout(c,1e3))}var a=0,b;c()}}}})(_),function(a,b){function f(a){var c=a[0].length;return b.all(a,function(a){return a.length===c})}function e(a){return b(a).chain().map(function(a,b){return[a,b]}).reduce(function(a,b){a[b[0]]=b[1];return a},{}).value()}function d(a){this.prototype=Error.prototype,this.name="InvalidArgument",this.message=a,this.toString=function(){return this.name+": "+this.message}}"use strict";var c={Alive:"*",Dead:"."};a.Support={InvalidArgument:d,CellTypes:c,invertObject:e,validateCanvas:function(a){if(!a||!b.isFunction(a.getContext))throw new d("Not a canvas element");return a},parseCellGrid:function(a){function i(a){var b=h[a];if(b===undefined)throw new d("Unknown cell symbol: "+a);return c[b]}var g=a.trim().split("\n"),h;if(g[0].length<1)throw new d("Cell grid is not a two-dimensional matrix");if(!f(g))throw new d("Cell grid is not a rectangle");h=e(c);return b.map(g,function(a){return b.map(a.split(""),i)})}}}(GameOfLife,_),function(a,b){"use strict";var c=a.Support.CellTypes;a.Graphics=function(a,d){function s(a){var b=(a+"").length*10+4;e.fillStyle="#ccc",e.fillRect(f-b,g-n,b,n),e.fillStyle="#555",e.fillText(a,o[0],o[1])}function r(a){e.fillStyle="#222",b.each(a,function(a,d){b.each(a,function(a,b){a===c.Alive&&e.fillRect(b*j+l,d*j+l,m,m)})})}function q(){var a,b;for(a=j+.5;a<f;a+=j)e.moveTo(a,0),e.lineTo(a,g);for(b=j+.5;b<g;b+=j)e.moveTo(0,b),e.lineTo(f,b);e.strokeStyle="#eee",e.stroke()}function p(){e.clearRect(0,0,f,g)}var e=a.getContext("2d"),f=a.width,g=a.height,h=d.length,i=d[0].length,j=f/i,k=j/2,l=2,m=j-l-1,n=16,o=[f-4,g-4];e.font="bold 10px sans-serif",e.textAlign="right",e.textBaseLine="top";return{drawFrame:function(a,b){p(),q(),r(a),s(b)}}}}(GameOfLife,_),function(a,b){function d(a,b){return a===c.Alive?b>=2&&b<=3?c.Alive:c.Dead:b===3?c.Alive:c.Dead}"use strict";var c=a.Support.CellTypes;a.Generation={evolveCell:d,tick:function(a){function i(a,d,e){return b.select(h(d,e),function(b){return a[b[1]][b[0]]===c.Alive}).length}function h(a,c){var d=[[a-1,c-1],[a,c-1],[a+1,c-1],[a-1,c],[a+1,c],[a-1,c+1],[a,c+1],[a+1,c+1]];return b.select(d,function(a){return g(a[0],a[1])})}function g(a,b){return a>=0&&a<f&&b>=0&&b<e}var e=a.length,f=a[0].length;return b.map(a,function(c,e){return b.map(c,function(b,c){return d(b,i(a,c,e))})})}}}(GameOfLife,_)
<commit_msg>Update snapshot release with the latest solution<commit_after>/*!
 * An implementation of Conway's Game of Life.
 *
 * Version: snapshot
 * <https://github.com/tkareine/game_of_life>
 *
 * Requires Underscore 1.1.6 or newer.
 *
 * Copyright (c) 2011 Tuomas Kareinen. Licensed under the MIT license.
 */(function(a){"use strict",window.GameOfLife=function(b,c){function g(b,c){return!a.isEqual(b,c)}var d=GameOfLife,e=d.Support.parseCellGrid(b),f=d.Graphics(d.Support.validateCanvas(c),e);return{evolve:function(){function c(){f.drawFrame(e,a),b=e,e=d.Generation.tick(b),g(b,e)&&(a+=1,setTimeout(c,500))}var a=0,b;c()}}}})(_),function(a,b){function f(a){var c=a[0].length;return b.all(a,function(a){return a.length===c})}function e(a){return b(a).chain().map(function(a,b){return[a,b]}).reduce(function(a,b){a[b[0]]=b[1];return a},{}).value()}function d(a){this.name="InvalidArgument",this.message=a}"use strict";var c={Alive:"*",Dead:"."};d.prototype=new Error,a.Support={InvalidArgument:d,CellTypes:c,invertObject:e,validateCanvas:function(a){if(!a||!b.isFunction(a.getContext))throw new d("Not a canvas element");return a},parseCellGrid:function(a){function i(a){var b=h[a];if(b===undefined)throw new d("Unknown cell symbol: "+a);return c[b]}var g=a.trim().split("\n"),h;if(g[0].length<1)throw new d("Cell grid is not a two-dimensional matrix");if(!f(g))throw new d("Cell grid is not a rectangle");h=e(c);return b.map(g,function(a){return b.map(a.split(""),i)})}}}(GameOfLife,_),function(a,b){"use strict";var c=a.Support.CellTypes;a.Graphics=function(a,d){function s(a){var b=(a+"").length*10+4;e.fillStyle="#ccc",e.fillRect(f-b,g-n,b,n),e.fillStyle="#555",e.fillText(a,o[0],o[1])}function r(a){e.fillStyle="#222",b.each(a,function(a,d){b.each(a,function(a,b){a===c.Alive&&e.fillRect(b*j+l,d*j+l,m,m)})})}function q(){var a,b;for(a=j+.5;a<f;a+=j)e.moveTo(a,0),e.lineTo(a,g);for(b=j+.5;b<g;b+=j)e.moveTo(0,b),e.lineTo(f,b);e.strokeStyle="#eee",e.stroke()}function p(){e.clearRect(0,0,f,g)}var e=a.getContext("2d"),f=a.width,g=a.height,h=d.length,i=d[0].length,j=f/i,k=j/2,l=2,m=j-l-1,n=16,o=[f-4,g-4];e.font="bold 10px sans-serif",e.textAlign="right",e.textBaseLine="top";return{drawFrame:function(a,b){p(),q(),r(a),s(b)}}}}(GameOfLife,_),function(a,b){function d(a,b){return a===c.Alive?b>=2&&b<=3?c.Alive:c.Dead:b===3?c.Alive:c.Dead}"use strict";var c=a.Support.CellTypes;a.Generation={evolveCell:d,tick:function(a){function i(a,d,e){return b.select(h(d,e),function(b){return a[b[1]][b[0]]===c.Alive}).length}function h(a,c){var d=[[a-1,c-1],[a,c-1],[a+1,c-1],[a-1,c],[a+1,c],[a-1,c+1],[a,c+1],[a+1,c+1]];return b.map(d,function(a){return g(a[0],a[1])})}function g(a,b){return[(a+f)%f,(b+e)%e]}var e=a.length,f=a[0].length;return b.map(a,function(c,e){return b.map(c,function(b,c){return d(b,i(a,c,e))})})}}}(GameOfLife,_)
<|endoftext|>


<commit_before>//TODO this is necessary during DEV, to reload bkg page
// var bkg = chrome.extension.getBackgroundPage();
// bkg.location.reload();
//reload code ends

document.addEventListener('DOMContentLoaded', function () {
  document.getElementById("getSelectionBtn").addEventListener('click', getSelectionHandler);

  //document.getElementById('lead').addEventListener('click', openPage);
  document.getElementById('decryptBtn').addEventListener('click', decryptPage);

  document.getElementById('aesGenBtn').addEventListener('click', genAES);
  document.getElementById('addFriend').addEventListener('click', addFriend);
});

function decryptPage() {

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

    chrome.tabs.sendMessage(tabs[0].id, {method: "getSelection"}, function(response){
      console.log("clicked");
      var myuid = JSON.parse(localStorage.getItem("me")).uid

      var encryptedMsg = response.data.split("\n");
      var nextIsUid = false;
      var parsedEncryptedMsg = ""
      console.log(encryptedMsg);
      for (var i in encryptedMsg) {
        // IF it's content parse the content
        if (nextIsUid) {
          console.log("=>  " + encryptedMsg[i]);
          if (myuid == encryptedMsg[i]) {
            console.log("found my uid damn!");
            i++;
            parsedEncryptedMsg = encryptedMsg[i];
            console.log(parsedEncryptedMsg);
            // At this point parsing is done, now decrypt and call contentscript
            var decryptedMsg = decrypt(myuid, parsedEncryptedMsg);
            console.log("Decrypted msg is :" + decryptedMsg);
            // Now communicate
            updateViewWithDecryptedMsg(decryptedMsg);

          }
          else {
            nextIsUid = false;
          }
        }
        if (encryptedMsg[i] == "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"){
          nextIsUid = true;
        }

      }

      // Now communicate to content script to update the view

    });
  });
}

function updateViewWithDecryptedMsg(decryptedMsg) {
  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    return chrome.tabs.sendMessage(tabs[0].id, {method: "updateViewWithDecryptedMessage", decryptedMsg:decryptedMsg}, null);
  });
}

// Send message to background script
function getSelectionHandler() {

	chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

	  chrome.tabs.sendMessage(tabs[0].id, {method: "encrypt"},

      function(res){

        var selectedElements = $('#friendSelect option:selected');
        var encryptedMsgs = "Message by www.dispeakable.me\n";
        encryptedMsgs += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
        $.each(selectedElements, function(i, ele){
          var uid = $(ele).attr("data-uid");
          encryptedMsgs += uid + "\n";
          encryptedMsgs += encrypt(uid, res);
          encryptedMsgs += "\n";
          encryptedMsgs += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
          // console.log(encrypted);
          // console.log(decrypt(uid, encrypted));
        });
        console.log(encryptedMsgs);
        chrome.tabs.sendMessage(tabs[0].id, {method:"updateViewWithEncryptedMessage", encryptedMessage: encryptedMsgs});

	  });
	});
}

var genAES = function(e){
  var pass = $('#password').val();
  var me = localStorage.getItem('me');
  var enc = GibberishAES.enc(me, pass);
  $('#aes').html(enc);
  e.preventDefault();
}

var addFriend = function(e){
  var fname = $('#friend_name').val();
  var secret = $('#f_secretKey').val();
  var fPasskey = $('#fPasskey').val();

  var dec = GibberishAES.dec(fPasskey, secret);

  var obj = JSON.parse(dec);
  obj.name = fname;

  var flist = JSON.parse(localStorage.getItem('friends')) ? JSON.parse(localStorage.getItem('friends')) : [];
  flist.push(obj);
  localStorage.setItem('friends', JSON.stringify(flist));

  var newFriend = $("<option></option>").attr("data-uid", obj.uid).html(fname);

  $("#friendSelect").append(newFriend);

  $('#friend_name').val("");
  $('#f_secretKey').val("");
  $('#fPasskey').val("");
  e.preventDefault();
}

var decrypt = function(uid, msg){
  var flist = JSON.parse(localStorage.getItem('friends'));
  for (var _i = 0; _i < flist.length; _i++){
    if (flist[_i].uid === uid){
      var decrypt = new JSEncrypt({default_key_size : 2048});
      decrypt.setPrivateKey(flist[_i].private);
      return decrypt.decrypt(msg);
    }
  }

  var me = JSON.parse(localStorage.getItem('me'));
  var decrypt = new JSEncrypt({default_key_size : 2048});
  decrypt.setPrivateKey(me.private);
  return decrypt.decrypt(msg);
}

var encrypt = function(uid, msg){
  var flist = JSON.parse(localStorage.getItem('friends'));
  for (var _i = 0; _i < flist.length; _i++){
    if (flist[_i].uid === uid){
      var encrypt = new JSEncrypt({default_key_size : 2048});
      // TODO : Should be public key. Library bug?
      encrypt.setPrivateKey(flist[_i].private);
      // encrypt.setPublicKey(flist[_i].public);
      return encrypt.encrypt(msg);
    }
  }
  // var me = JSON.parse(localStorage.getItem('me'));
  // var decrypt = new JSEncrypt({default_key_size : 2048});
  // decrypt.setPrivateKey(me.private);
  // return decrypt.encrypt(msg);
}

//WILS AREA, STAY THE FUCK OUT!!!
// (function($){
  pageInitialized = false;
  $(function() {
    if(pageInitialized) return;
    pageInitialized = true;
    chrome.tabs.insertCSS(null, {file: "inject.css"});
    // Handler for .ready() called.
    var $goggles = $('#goggles');
    var mouseleft = false;
    $(document).on('mouseup', function(e){
      $goggles.css({
        'top': 33,
        'left': 29
      });
      if(e.pageX<0 || e.pageX>300 || e.pageY < 0 || e.pageY > 626){
        //TODO send message to background
        chrome.tabs.executeScript(null, {file: "spy_goggles.js"});
        $goggles.hide();
        // chrome.runtime.sendMessage({greeting: "potato"}, function(response) {
        //   if(response.farewell == "banana"){
        //     $goggles.hide();
        //   }else{
        //     console.log(response.farewell);
        //   }
        // });
      }
      return false;
    });
    $goggles.draggable();
  });
// })(jQuery);

//END OF WILS AREA
<commit_msg>disable goggles<commit_after>//TODO this is necessary during DEV, to reload bkg page
// var bkg = chrome.extension.getBackgroundPage();
// bkg.location.reload();
//reload code ends

document.addEventListener('DOMContentLoaded', function () {
  document.getElementById("getSelectionBtn").addEventListener('click', getSelectionHandler);

  //document.getElementById('lead').addEventListener('click', openPage);
  document.getElementById('decryptBtn').addEventListener('click', decryptPage);

  document.getElementById('aesGenBtn').addEventListener('click', genAES);
  document.getElementById('addFriend').addEventListener('click', addFriend);
});

function decryptPage() {

  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

    chrome.tabs.sendMessage(tabs[0].id, {method: "getSelection"}, function(response){
      console.log("clicked");
      var myuid = JSON.parse(localStorage.getItem("me")).uid

      var encryptedMsg = response.data.split("\n");
      var nextIsUid = false;
      var parsedEncryptedMsg = ""
      console.log(encryptedMsg);
      for (var i in encryptedMsg) {
        // IF it's content parse the content
        if (nextIsUid) {
          console.log("=>  " + encryptedMsg[i]);
          if (myuid == encryptedMsg[i]) {
            console.log("found my uid damn!");
            i++;
            parsedEncryptedMsg = encryptedMsg[i];
            console.log(parsedEncryptedMsg);
            // At this point parsing is done, now decrypt and call contentscript
            var decryptedMsg = decrypt(myuid, parsedEncryptedMsg);
            console.log("Decrypted msg is :" + decryptedMsg);
            // Now communicate
            updateViewWithDecryptedMsg(decryptedMsg);

          }
          else {
            nextIsUid = false;
          }
        }
        if (encryptedMsg[i] == "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"){
          nextIsUid = true;
        }

      }

      // Now communicate to content script to update the view

    });
  });
}

function updateViewWithDecryptedMsg(decryptedMsg) {
  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    return chrome.tabs.sendMessage(tabs[0].id, {method: "updateViewWithDecryptedMessage", decryptedMsg:decryptedMsg}, null);
  });
}

// Send message to background script
function getSelectionHandler() {

	chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

	  chrome.tabs.sendMessage(tabs[0].id, {method: "encrypt"},

      function(res){

        var selectedElements = $('#friendSelect option:selected');
        var encryptedMsgs = "Message by www.dispeakable.me\n";
        encryptedMsgs += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
        $.each(selectedElements, function(i, ele){
          var uid = $(ele).attr("data-uid");
          encryptedMsgs += uid + "\n";
          encryptedMsgs += encrypt(uid, res);
          encryptedMsgs += "\n";
          encryptedMsgs += "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
          // console.log(encrypted);
          // console.log(decrypt(uid, encrypted));
        });
        console.log(encryptedMsgs);
        chrome.tabs.sendMessage(tabs[0].id, {method:"updateViewWithEncryptedMessage", encryptedMessage: encryptedMsgs});

	  });
	});
}

var genAES = function(e){
  var pass = $('#password').val();
  var me = localStorage.getItem('me');
  var enc = GibberishAES.enc(me, pass);
  $('#aes').html(enc);
  e.preventDefault();
}

var addFriend = function(e){
  var fname = $('#friend_name').val();
  var secret = $('#f_secretKey').val();
  var fPasskey = $('#fPasskey').val();

  var dec = GibberishAES.dec(fPasskey, secret);

  var obj = JSON.parse(dec);
  obj.name = fname;

  var flist = JSON.parse(localStorage.getItem('friends')) ? JSON.parse(localStorage.getItem('friends')) : [];
  flist.push(obj);
  localStorage.setItem('friends', JSON.stringify(flist));

  var newFriend = $("<option></option>").attr("data-uid", obj.uid).html(fname);

  $("#friendSelect").append(newFriend);

  $('#friend_name').val("");
  $('#f_secretKey').val("");
  $('#fPasskey').val("");
  e.preventDefault();
}

var decrypt = function(uid, msg){
  var flist = JSON.parse(localStorage.getItem('friends'));
  for (var _i = 0; _i < flist.length; _i++){
    if (flist[_i].uid === uid){
      var decrypt = new JSEncrypt({default_key_size : 2048});
      decrypt.setPrivateKey(flist[_i].private);
      return decrypt.decrypt(msg);
    }
  }

  var me = JSON.parse(localStorage.getItem('me'));
  var decrypt = new JSEncrypt({default_key_size : 2048});
  decrypt.setPrivateKey(me.private);
  return decrypt.decrypt(msg);
}

var encrypt = function(uid, msg){
  var flist = JSON.parse(localStorage.getItem('friends'));
  for (var _i = 0; _i < flist.length; _i++){
    if (flist[_i].uid === uid){
      var encrypt = new JSEncrypt({default_key_size : 2048});
      // TODO : Should be public key. Library bug?
      encrypt.setPrivateKey(flist[_i].private);
      // encrypt.setPublicKey(flist[_i].public);
      return encrypt.encrypt(msg);
    }
  }
  // var me = JSON.parse(localStorage.getItem('me'));
  // var decrypt = new JSEncrypt({default_key_size : 2048});
  // decrypt.setPrivateKey(me.private);
  // return decrypt.encrypt(msg);
}

//WILS AREA, STAY THE FUCK OUT!!!
// (function($){
  pageInitialized = false;
  $(function() {
    if(pageInitialized) return;
    pageInitialized = true;
    chrome.tabs.insertCSS(null, {file: "inject.css"});
    // Handler for .ready() called.
    var $goggles = $('#goggles');
    var mouseleft = false;
    $(document).on('mouseup', function(e){
      $goggles.css({
        'top': 33,
        'left': 29
      });
      if(e.pageX<0 || e.pageX>300 || e.pageY < 0 || e.pageY > 626){
        //TODO send message to background
        //chrome.tabs.executeScript(null, {file: "spy_goggles.js"});
        $goggles.hide();
        decryptPage();
        // chrome.runtime.sendMessage({greeting: "potato"}, function(response) {
        //   if(response.farewell == "banana"){
        //     $goggles.hide();
        //   }else{
        //     console.log(response.farewell);
        //   }
        // });
      }
      return false;
    });
    $goggles.draggable();
  });
// })(jQuery);

//END OF WILS AREA
<|endoftext|>