<commit_before>"use strict";

var async        = require("async");
var mailboxNames = require("./names.json");

/**
 * Expose to the world
 * @namespace mailbox
 */
module.exports.Mailbox = Mailbox;
module.exports.detectMailboxType = detectMailboxType;

/**
 * Create a mailbox object
 *
 * @memberOf mailbox
 * @constructor
 * @param {Object} options Options object
 */
function Mailbox(options){

    options = options || {};

    Object.defineProperty(this, "client", {
        value: options.client || {},
        enumerable: false
    });

    Object.defineProperty(this, "tags", {
        value: options.tags || [],
        enumerable: false,
        writable: true
    });

    this.name = options.name || "";
    this.path = options.path || this.name;
    this.type = options.type || (this.client._capabilities.indexOf("XLIST")<0 && this.detectType() || "Normal");
    this.delimiter = options.delimiter || this.client._mailboxDelimiter || "";
}

/**
 * Open the mailbox
 *
 * @param {Object} [options] Optional options object
 * @param {Boolean} [options.readOnly] If set to true, open the mailbox in read-only mode (seen/unseen flags won't be touched)
 * @param {Function} callback Callback function to run when the mailbox is opened
 */
Mailbox.prototype.open = function(options, callback){
    this.client.openMailbox(this.path, options, callback);
};

/**
 * Detects the type by the name of the mailbox
 */
Mailbox.prototype.detectType = function(){
    return detectMailboxType(this.name);
};

/**
 * Lists children for the mailbox
 *
 * @param {String} [path] If set, list only selected path info but not the children
 * @param {Function} callback Callback function to run with the mailbox list
 */

Mailbox.prototype.listChildren = function(path, all, callback){

    if(!callback && typeof all == "function"){
        callback = all;
        all = undefined;
    }

    if(!callback && typeof path == "function"){
        callback = path;
        path = undefined;
    }

    var command = "LIST", suffix = "", wildcard = all ? "*" : "%";

    path = this.client._escapeString(path || (this.path ? this.path + this.delimiter + wildcard : wildcard));

    if(this.client._capabilities.indexOf("SPECIAL-USE")>=0){
        command = "LIST";
        suffix = " RETURN (SPECIAL-USE)";
    }else if(this.client._capabilities.indexOf("XLIST")>=0){
        command = "XLIST";
    }

    this.client._send(command+" "+this.client._escapeString(this.client._rootPath) + " " + path + suffix,
        (function(){
            this.listSubscribed(path, this.client._mailboxList, callback);
        }).bind(this),
        (function(){
            this.client._mailboxList = [];
        }).bind(this));

};

/**
 * Fetches subscribed mailboxes
 *
 * @param {String} path Parent mailbox
 * @param {Array} xinfo Results from XLIST or LIST
 * @param {Function} callback Callback function to run with the mailbox list
 */
Mailbox.prototype.listSubscribed = function(path, xinfo, callback){

    if(!callback && typeof xinfo == "function"){
        callback = xinfo;
        xinfo = undefined;
    }

    xinfo = xinfo || [];

    this.client._send("LSUB "+this.client._escapeString(this.client._rootPath)+" "+path,
        (function(status){
            if(!this.client._mailboxList.length){
                this.client._mailboxList = [].concat(xinfo);
            }
            this.client._handlerTaggedLsub(xinfo, callback, status);
        }).bind(this),
        (function(){
            this.client._mailboxList = [];
        }).bind(this));
};

Mailbox.prototype.subscribeChild = function(path, callback){

    this.client._send("SUBSCRIBE "+this.client._escapeString(path), (function(status){
        if(typeof callback == "function"){
            if(status == "OK"){
                callback(null);
            } else {
                callback(new Error("Subcribing to mailbox failed"));
            }
        }
    }).bind(this));
};

Mailbox.prototype.unsubscribeChild = function(path, callback){

    this.client._send("UNSUBSCRIBE "+this.client._escapeString(path), (function(status){
        if(typeof callback == "function"){
            if(status == "OK"){
                callback(null);
            } else {
                callback(new Error("Unsubcribing to mailbox failed"));
            }
        }
    }).bind(this));
};

/**
 * Creates a new mailbox and subscribes to it
 *
 * @param {String} name Name of the mailbox
 * @param {Function} callback Callback function to run with the created mailbox object
 */
Mailbox.prototype.createChild = function(name, callback){
    var path = (this.path ? this.path + this.delimiter + name:name);
    this.client._send("CREATE "+this.client._escapeString(path), (function(status){
        if(status == "OK"){
            this.client._send("SUBSCRIBE "+this.client._escapeString(path), (function(){
                if(typeof callback == "function"){
                    callback(null, new Mailbox({
                        client: this.client,
                        path: path,
                        name: name,
                        delimiter: this.delimiter,
                        tags: []
                    }));
                }
            }).bind(this));
        }else{
            callback(new Error("Creating mailbox failed"));
        }
    }).bind(this));
};

/**
 * Renames an existing mailbox and subscribes to it
 *
 * @param {String} oldName Old name of the mailbox
 * @param {String} newName New name for the mailbox
 * @param {Function} callback Callback function to run with the created mailbox object
 */
Mailbox.prototype.renameChild = function(oldName, newName, callback){

    var oldPath = (this.path ? this.path + this.delimiter + oldName:oldName);
    var newPath = (this.path ? this.path + this.delimiter + newName:newName);

    this.client._send("RENAME " + this.client._escapeString(oldPath) + " " + this.client._escapeString(newPath), (function(status){
        if(status == "OK"){
            this.name = newName;
            if(typeof callback == "function"){
                callback(null, this);
            }
        }else{
            callback(new Error("Renaming mailbox failed"));
        }
    }).bind(this));
};

/**
 * Deletes a mailbox
 *
 * @param {String} name Name of the mailbox
 * @param {Function} callback Callback function to run with the status of the operation
 */
Mailbox.prototype.deleteChild = function(name, callback){
    var path = (this.path ? this.path + this.delimiter + name:name);
    this.client._send("DELETE "+this.client._escapeString(path), (function(status){
        if(status == "OK"){
            callback(null, status);
        }else{
            callback(new Error("Deleting mailbox failed"));
        }
    }).bind(this));
};

/**
 * Returns mailbox type detected by the name of the mailbox
 *
 * @param {String} mailboxName Mailbox name
 * @return {String} Mailbox type
 */
function detectMailboxType(mailboxName){
    mailboxName = (mailboxName || "").toString().trim().toLowerCase();

    if(mailboxNames.sent.indexOf(mailboxName)>=0){
        return "Sent";
    }

    if(mailboxNames.trash.indexOf(mailboxName)>=0){
        return "Trash";
    }

    if(mailboxNames.junk.indexOf(mailboxName)>=0){
        return "Junk";
    }

    if(mailboxNames.drafts.indexOf(mailboxName)>=0){
        return "Drafts";
    }

    return "Normal";
}

Mailbox.prototype.getMetadata = function( box, name, callback  ){

    this.client._send("GETMETADATA "+this.client._escapeString(box.path)+" "+name, (function(status){

        if(status == "OK"){
            callback(null, status);
        }else{
            // To Do -> boxes with disabled attribute should be ignored. The other should throw an error
            callback(null, status);
        }
    }).bind(this));

};
<commit_msg>Omit listSuscribed() mailboxes<commit_after>"use strict";

var async        = require("async");
var mailboxNames = require("./names.json");

/**
 * Expose to the world
 * @namespace mailbox
 */
module.exports.Mailbox = Mailbox;
module.exports.detectMailboxType = detectMailboxType;

/**
 * Create a mailbox object
 *
 * @memberOf mailbox
 * @constructor
 * @param {Object} options Options object
 */
function Mailbox(options){

    options = options || {};

    Object.defineProperty(this, "client", {
        value: options.client || {},
        enumerable: false
    });

    Object.defineProperty(this, "tags", {
        value: options.tags || [],
        enumerable: false,
        writable: true
    });

    this.name = options.name || "";
    this.path = options.path || this.name;
    this.type = options.type || (this.client._capabilities.indexOf("XLIST")<0 && this.detectType() || "Normal");
    this.delimiter = options.delimiter || this.client._mailboxDelimiter || "";
}

/**
 * Open the mailbox
 *
 * @param {Object} [options] Optional options object
 * @param {Boolean} [options.readOnly] If set to true, open the mailbox in read-only mode (seen/unseen flags won't be touched)
 * @param {Function} callback Callback function to run when the mailbox is opened
 */
Mailbox.prototype.open = function(options, callback){
    this.client.openMailbox(this.path, options, callback);
};

/**
 * Detects the type by the name of the mailbox
 */
Mailbox.prototype.detectType = function(){
    return detectMailboxType(this.name);
};

/**
 * Lists children for the mailbox
 *
 * @param {String} [path] If set, list only selected path info but not the children
 * @param {Function} callback Callback function to run with the mailbox list
 */

Mailbox.prototype.listChildren = function(path, all, callback){

    if(!callback && typeof all == "function"){
        callback = all;
        all = undefined;
    }

    if(!callback && typeof path == "function"){
        callback = path;
        path = undefined;
    }

    var command = "LIST", suffix = "", wildcard = all ? "*" : "%";

    path = this.client._escapeString(path || (this.path ? this.path + this.delimiter + wildcard : wildcard));

    if(this.client._capabilities.indexOf("SPECIAL-USE")>=0){
        command = "LIST";
        suffix = " RETURN (SPECIAL-USE)";
    }else if(this.client._capabilities.indexOf("XLIST")>=0){
        command = "XLIST";
    }

    this.client._send(command+" "+this.client._escapeString(this.client._rootPath) + " " + path + suffix,
        (function(){

          //this.listSubscribed(path, this.client._mailboxList, callback);
          callback( null, this.client._mailboxList );

        }).bind(this),
        (function(){
            this.client._mailboxList = [];
        }).bind(this));

};

/**
 * Fetches subscribed mailboxes
 *
 * @param {String} path Parent mailbox
 * @param {Array} xinfo Results from XLIST or LIST
 * @param {Function} callback Callback function to run with the mailbox list
 */
Mailbox.prototype.listSubscribed = function(path, xinfo, callback){

    if(!callback && typeof xinfo == "function"){
        callback = xinfo;
        xinfo = undefined;
    }

    xinfo = xinfo || [];

    this.client._send("LSUB "+this.client._escapeString(this.client._rootPath)+" "+path,
        (function(status){
            if(!this.client._mailboxList.length){
                this.client._mailboxList = [].concat(xinfo);
            }
            this.client._handlerTaggedLsub(xinfo, callback, status);
        }).bind(this),
        (function(){
            this.client._mailboxList = [];
        }).bind(this));
};

Mailbox.prototype.subscribeChild = function(path, callback){

    this.client._send("SUBSCRIBE "+this.client._escapeString(path), (function(status){
        if(typeof callback == "function"){
            if(status == "OK"){
                callback(null);
            } else {
                callback(new Error("Subcribing to mailbox failed"));
            }
        }
    }).bind(this));
};

Mailbox.prototype.unsubscribeChild = function(path, callback){

    this.client._send("UNSUBSCRIBE "+this.client._escapeString(path), (function(status){
        if(typeof callback == "function"){
            if(status == "OK"){
                callback(null);
            } else {
                callback(new Error("Unsubcribing to mailbox failed"));
            }
        }
    }).bind(this));
};

/**
 * Creates a new mailbox and subscribes to it
 *
 * @param {String} name Name of the mailbox
 * @param {Function} callback Callback function to run with the created mailbox object
 */
Mailbox.prototype.createChild = function(name, callback){
    var path = (this.path ? this.path + this.delimiter + name:name);
    this.client._send("CREATE "+this.client._escapeString(path), (function(status){
        if(status == "OK"){
            this.client._send("SUBSCRIBE "+this.client._escapeString(path), (function(){
                if(typeof callback == "function"){
                    callback(null, new Mailbox({
                        client: this.client,
                        path: path,
                        name: name,
                        delimiter: this.delimiter,
                        tags: []
                    }));
                }
            }).bind(this));
        }else{
            callback(new Error("Creating mailbox failed"));
        }
    }).bind(this));
};

/**
 * Renames an existing mailbox and subscribes to it
 *
 * @param {String} oldName Old name of the mailbox
 * @param {String} newName New name for the mailbox
 * @param {Function} callback Callback function to run with the created mailbox object
 */
Mailbox.prototype.renameChild = function(oldName, newName, callback){

    var oldPath = (this.path ? this.path + this.delimiter + oldName:oldName);
    var newPath = (this.path ? this.path + this.delimiter + newName:newName);

    this.client._send("RENAME " + this.client._escapeString(oldPath) + " " + this.client._escapeString(newPath), (function(status){
        if(status == "OK"){
            this.name = newName;
            if(typeof callback == "function"){
                callback(null, this);
            }
        }else{
            callback(new Error("Renaming mailbox failed"));
        }
    }).bind(this));
};

/**
 * Deletes a mailbox
 *
 * @param {String} name Name of the mailbox
 * @param {Function} callback Callback function to run with the status of the operation
 */
Mailbox.prototype.deleteChild = function(name, callback){
    var path = (this.path ? this.path + this.delimiter + name:name);
    this.client._send("DELETE "+this.client._escapeString(path), (function(status){
        if(status == "OK"){
            callback(null, status);
        }else{
            callback(new Error("Deleting mailbox failed"));
        }
    }).bind(this));
};

/**
 * Returns mailbox type detected by the name of the mailbox
 *
 * @param {String} mailboxName Mailbox name
 * @return {String} Mailbox type
 */
function detectMailboxType(mailboxName){
    mailboxName = (mailboxName || "").toString().trim().toLowerCase();

    if(mailboxNames.sent.indexOf(mailboxName)>=0){
        return "Sent";
    }

    if(mailboxNames.trash.indexOf(mailboxName)>=0){
        return "Trash";
    }

    if(mailboxNames.junk.indexOf(mailboxName)>=0){
        return "Junk";
    }

    if(mailboxNames.drafts.indexOf(mailboxName)>=0){
        return "Drafts";
    }

    return "Normal";
}

Mailbox.prototype.getMetadata = function( box, name, callback  ){

    this.client._send("GETMETADATA "+this.client._escapeString(box.path)+" "+name, (function(status){

        if(status == "OK"){
            callback(null, status);
        }else{
            // To Do -> boxes with disabled attribute should be ignored. The other should throw an error
            callback(null, status);
        }
    }).bind(this));

};
<|endoftext|>


<commit_before>var mime = require( 'mime-lib' )
var Iconv = require( 'iconv-lite' )

function Body( header, body, envelope ) {

  var boundary = header.contentType &&
    header.contentType.boundary

  if( boundary ) {

    var start = body.indexOf( '--' + boundary + '\r\n' )
    var end   = body.lastIndexOf( '--' + boundary + '--' )

    if( ~start ) {

      var parts = body
        .slice( start + boundary.length + 4, end )
        .split( '--' + boundary + '\r\n' )

      for( var i = 0; i < parts.length; i++ ) {
        this[i] = require('../envelope')( parts[i] )
      }

    } else {
      boundary = null
    }

  }

  if( !boundary ) {

    var isText = header.contentType &&
      header.contentType.mime &&
      ~header.contentType.mime.indexOf( 'text' )

    this[0] = body.trim()

    // Automatically create a buffer from
    // non-text base64 encoded data
    if( !isText && /^base64$/i.test( header.contentTransferEncoding ) ) {
      this[0] = new Buffer( this[0], 'base64' )
    }

    // Try to convert to UTF8, if it's not UTF8 yet
    var charset = header.contentType &&
      header.contentType.charset

    // Automatically decode text from either
    // base64 or quoted-printable encoding
    if( isText ) {
      if( /^quoted-printable$/i.test( header.contentTransferEncoding ) )
        this[0] = mime.decodeQP( this[0], charset )
      if( /^base64$/i.test( header.contentTransferEncoding ) )
        this[0] = new Buffer( this[0], 'base64' ).toString()
    }

    if( !isText && charset ) {
      if( Iconv.encodingExists( charset ) ) {
        this[0] = Iconv.decode( this[0], charset )
      }
    }

    // Convert this part to an Envelope,
    // if this part appears to be an attached message
    if( header.contentType && /^message\/rfc822$/i.test( header.contentType.mime ) ) {
      this[0] = require('../envelope')( this[0] )
    }

  }

}

Body.prototype = Object.create( null )

module.exports = Body
<commit_msg>fix(body): Replace use of Buffer ctor with Buffer.from()<commit_after>var mime = require( 'mime-lib' )
var Iconv = require( 'iconv-lite' )

function Body( header, body, envelope ) {

  var boundary = header.contentType &&
    header.contentType.boundary

  if( boundary ) {

    var start = body.indexOf( '--' + boundary + '\r\n' )
    var end   = body.lastIndexOf( '--' + boundary + '--' )

    if( ~start ) {

      var parts = body
        .slice( start + boundary.length + 4, end )
        .split( '--' + boundary + '\r\n' )

      for( var i = 0; i < parts.length; i++ ) {
        this[i] = require('../envelope')( parts[i] )
      }

    } else {
      boundary = null
    }

  }

  if( !boundary ) {

    var isText = header.contentType &&
      header.contentType.mime &&
      ~header.contentType.mime.indexOf( 'text' )

    this[0] = body.trim()

    // Automatically create a buffer from
    // non-text base64 encoded data
    if( !isText && /^base64$/i.test( header.contentTransferEncoding ) ) {
      this[0] = Buffer.from( this[0], 'base64' )
    }

    // Try to convert to UTF8, if it's not UTF8 yet
    var charset = header.contentType &&
      header.contentType.charset

    // Automatically decode text from either
    // base64 or quoted-printable encoding
    if( isText ) {
      if( /^quoted-printable$/i.test( header.contentTransferEncoding ) )
        this[0] = mime.decodeQP( this[0], charset )
      if( /^base64$/i.test( header.contentTransferEncoding ) )
        this[0] = Buffer.from( this[0], 'base64' ).toString()
    }

    if( !isText && charset ) {
      if( Iconv.encodingExists( charset ) ) {
        this[0] = Iconv.decode( this[0], charset )
      }
    }

    // Convert this part to an Envelope,
    // if this part appears to be an attached message
    if( header.contentType && /^message\/rfc822$/i.test( header.contentType.mime ) ) {
      this[0] = require('../envelope')( this[0] )
    }

  }

}

Body.prototype = Object.create( null )

module.exports = Body
<|endoftext|>


<commit_before>var bane = require("bane");
var args = require("./buster-cli/args");
var help = require("./buster-cli/help");
var logger = require("./buster-cli/logger");
var config = require("./buster-cli/config");

function F() {}
function create(obj) {
    F.prototype = obj;
    return new F();
}

function BusterCli(options) {
    var cliArgs = create(args);
    this.args = cliArgs;
    this.opt = cliArgs.opt.bind(cliArgs);
    this.opd = cliArgs.opd.bind(cliArgs);
    this.shorthand = cliArgs.addShorthand.bind(cliArgs);
    this.environmentVariable = options && options.environmentVariable;
    var cliHelp = help.create(this, options || {});
    this.addHelpOption = cliHelp.addHelpOption.bind(cliHelp);
}

// Public API

module.exports = BusterCli.prototype = bane.createEventEmitter({
    validators: args.validators,

    // Create a cli helper. Options:
    // {
    //     // Formatting options
    //     width: 80,  // Total width of any printed help
    //     indent: 4,  // Indent from left edge for printed help
    //     spacing: 3, // Spaces between options and explanations in help
    // }
    //
    create: function (options) {
        return new BusterCli(options);
    },

    environmentArgs: function () {
        var envVar = this.environmentVariable;
        if (!process.env[envVar]) { return []; }
        return process.env[envVar].split(" ");
    },

    parseArgs: function (args, callback) {
        args = this.environmentArgs().concat(args);
        this.args.parse(args, function (errors, options) {
            if (errors) {
                this.logger.error(errors[0]);
            } else {
                this.emit("args:parsed", options);
            }
            callback(errors, options);
        }.bind(this));
    },

    createLogger: function (stdout, stderr) {
        this.logger = logger.createFor(this, stdout, stderr);
        return this.logger;
    },

    addConfigOption: function (baseName, defaultFiles) {
        var cfg = config.create(this, {
            baseName: baseName,
            defaultFiles: defaultFiles
        });
        cfg.addGroupOption();
        cfg.addTestsOption();
        cfg.addEnvOption();
        this.loadConfig = cfg.loadConfig.bind(cfg);
    },

    pref: function (prefs, arg, property) {
        var argValue = arg.value || arg.isSet;
        if (arg.isSet || !prefs) { return argValue; }
        return prefs.get(property, argValue);
    },

    exit: function (code) {
        process.exit(code || 0);
    },

    err: function (message) {
        this.logger.error(message);
        this.exit(1);
    }
});
<commit_msg>fix for issue #374: autotest output on windows<commit_after>var bane = require("bane");
var args = require("./buster-cli/args");
var help = require("./buster-cli/help");
var logger = require("./buster-cli/logger");
var config = require("./buster-cli/config");

function F() {}
function create(obj) {
    F.prototype = obj;
    return new F();
}

function BusterCli(options) {
    var cliArgs = create(args);
    this.args = cliArgs;
    this.opt = cliArgs.opt.bind(cliArgs);
    this.opd = cliArgs.opd.bind(cliArgs);
    this.shorthand = cliArgs.addShorthand.bind(cliArgs);
    this.environmentVariable = options && options.environmentVariable;
    var cliHelp = help.create(this, options || {});
    this.addHelpOption = cliHelp.addHelpOption.bind(cliHelp);
}

// Public API

module.exports = BusterCli.prototype = bane.createEventEmitter({
    validators: args.validators,

    // Create a cli helper. Options:
    // {
    //     // Formatting options
    //     width: 80,  // Total width of any printed help
    //     indent: 4,  // Indent from left edge for printed help
    //     spacing: 3, // Spaces between options and explanations in help
    // }
    //
    create: function (options) {
        return new BusterCli(options);
    },

    environmentArgs: function () {
        var envVar = this.environmentVariable;
        if (!process.env[envVar]) { return []; }
        return process.env[envVar].split(" ");
    },

    parseArgs: function (args, callback) {
        args = this.environmentArgs().concat(args);
        this.args.parse(args, function (errors, options) {
            if (errors) {
                this.logger.error(errors[0]);
            } else {
                this.emit("args:parsed", options);
            }
            callback(errors, options);
        }.bind(this));
    },

    createLogger: function (stdout, stderr) {
        this.logger = logger.createFor(this, stdout, stderr);
        return this.logger;
    },

    addConfigOption: function (baseName, defaultFiles) {
        var cfg = config.create(this, {
            baseName: baseName,
            defaultFiles: defaultFiles
        });
        cfg.addGroupOption();
        cfg.addTestsOption();
        cfg.addEnvOption();
        this.loadConfig = cfg.loadConfig.bind(cfg);
    },

    pref: function (prefs, arg, property) {
        var argValue = arg.value || arg.isSet;
        if (arg.isSet || !prefs) { return argValue; }
        return prefs.get(property, argValue);
    },

    exit: function (code) {
        setTimeout(process.exit.bind(null, code || 0), 5);
    },

    err: function (message) {
        this.logger.error(message);
        this.exit(1);
    }
});
<|endoftext|>


<commit_before>// takes a post link and returns its comment url
function getCommentURL( linkToPost ) {
	var postCell,
		postRow,
		commentRow,
		commentLink,
		commentURL;

	postCell = linkToPost.parentNode;  // get table cell of link
	postRow = postCell.parentNode;	// get table row of link
	commentRow = postRow.nextElementSibling;  // go to next row (containing comment)

	// check if next row was found
	if( commentRow ) {
		commentLink = commentRow.querySelector("a:last-child");  // get the last link in that row
		// comments don't exist for "x is hiring" listings
		if ( commentLink )
			commentURL = commentLink.getAttribute("href");	// get the href attribute of comment link

		// return comment url
		return commentURL;
	}
}

// convert nodeList to array and get rid
function nodelistToArray( nodelist ) {
	var array = [];

	for (var i = 0; i < nodelist.length; i++ ) {
		var currentPost = nodelist[i];  // the node for the current post

		// Add node to array
		array.push( currentPost );
	}

	return array;
}

var linkList,
	linkArray,
	commentList = [];

// grab all links including "more" link and convert to array of objects
linkList = document.querySelectorAll( "td.title a" );
linkArray = nodelistToArray( linkList );

// use < to omit "more"
for (var i = 0; i < linkArray.length; i++) {
	var link 	= linkArray[i],
		comment = getCommentURL( link );

	if ( comment ) {
		console.log( comment );
	}
};
<commit_msg>Pushes all comments to an associative array.<commit_after>// takes a post link and returns its comment url
function getCommentURL( linkToPost ) {
	var postCell,
		postRow,
		commentRow,
		commentLink,
		commentURL;

	postCell = linkToPost.parentNode;  // get table cell of link
	postRow = postCell.parentNode;	// get table row of link
	commentRow = postRow.nextElementSibling;  // go to next row (containing comment)

	// check if next row was found
	if( commentRow ) {
		commentLink = commentRow.querySelector("a:last-child");  // get the last link in that row
		// comments don't exist for "x is hiring" listings
		if ( commentLink )
			commentURL = commentLink.getAttribute("href");	// get the href attribute of comment link

		// return comment url
		return commentURL;
	}
}

// convert nodeList to array and get rid
function nodelistToArray( nodelist ) {
	var array = [];

	for (var i = 0; i < nodelist.length; i++ ) {
		var currentPost = nodelist[i];  // the node for the current post

		// Add node to array
		array.push( currentPost );
	}

	return array;
}

var linkList,
	linkArray,
	commentList = [];

// grab all links including "more" link and convert to array of objects
linkList = document.querySelectorAll( "td.title a" );
linkArray = nodelistToArray( linkList );

// use < to omit "more"
for (var i = 0; i < linkArray.length; i++) {
	var link 	= linkArray[i],
		comment = getCommentURL( link );

	if ( comment ) {
		commentList[ link ] = comment;
	}
};

console.log( commentList );<|endoftext|>


<commit_before>exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)

exports.blobConstructor = false
try {
	new Blob([new ArrayBuffer(1)])
	exports.blobConstructor = true
} catch (e) {}

var xhr = new global.XMLHttpRequest()
// If XDomainRequest is available (ie only, where xhr might not work
// cross domain), use the page location. Otherwise use example.com
xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')

function checkTypeSupport (type) {
	try {
		xhr.responseType = type
		return xhr.responseType === type
	} catch (e) {}
	return false
}

// For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'.
// Safari 7.1 appears to have fixed this bug.
var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined'
var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice)

exports.arraybuffer = haveArrayBuffer && checkTypeSupport('arraybuffer')
// These next two tests unavoidably show warnings in Chrome. Since fetch will always
// be used if it's available, just return false for these to avoid the warnings.
exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream')
exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer &&
	checkTypeSupport('moz-chunked-arraybuffer')
exports.overrideMimeType = isFunction(xhr.overrideMimeType)
exports.vbArray = isFunction(global.VBArray)

function isFunction (value) {
  return typeof value === 'function'
}

xhr = null // Help gc
<commit_msg>Adding support for Service Workers.<commit_after>exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)

exports.blobConstructor = false
try {
	new Blob([new ArrayBuffer(1)])
	exports.blobConstructor = true
} catch (e) {}

// Service workers don't have XHR
if (global.XMLHttpRequest) {
	var xhr = new global.XMLHttpRequest()
	// If XDomainRequest is available (ie only, where xhr might not work
	// cross domain), use the page location. Otherwise use example.com
	xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com')
} else {
	var xhr = null
}

function checkTypeSupport (type) {
	if (!xhr) return false
	try {
		xhr.responseType = type
		return xhr.responseType === type
	} catch (e) {}
	return false
}

// For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'.
// Safari 7.1 appears to have fixed this bug.
var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined'
var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice)

exports.arraybuffer = haveArrayBuffer && checkTypeSupport('arraybuffer')
// These next two tests unavoidably show warnings in Chrome. Since fetch will always
// be used if it's available, just return false for these to avoid the warnings.
exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream')
exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer &&
	checkTypeSupport('moz-chunked-arraybuffer')
exports.overrideMimeType = xhr ? isFunction(xhr.overrideMimeType) : false
exports.vbArray = isFunction(global.VBArray)

function isFunction (value) {
  return typeof value === 'function'
}

xhr = null // Help gc
<|endoftext|>


<commit_before>const { getActiveTab } = require('tabs/utils');

function Minimap(sidebar) {
    var minimap = this;
    minimap.sidebar = sidebar;  // FIXME: will this leak when destroying windows ?
    let sidebarDocument = minimap.sidebar.browser.contentDocument;

    minimap.isdown = false;
    sidebarDocument.documentElement.addEventListener('mousedown', function(e) {
        minimap.isdown = true;
        minimap.clickScrollMinimap(e);
    });

    sidebarDocument.documentElement.addEventListener('wheel', function(e) {
        minimap.wheelScrollMinimap(e);
    });

    sidebarDocument.documentElement.addEventListener('mouseup', function(e) {
        minimap.isdown = false;
    });

    sidebarDocument.documentElement.addEventListener('mousemove', function(e) {
        if (minimap.isdown) {
            minimap.clickScrollMinimap(e);
        }
    });
};

Minimap.prototype.getContentWindow = function() {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let win = this.sidebar.window;
    let contentWindow = getActiveTab(win).linkedBrowser.contentWindow;
    // let index = win.gBrowser.getBrowserIndexForDocument(contentWindow.document);
    return contentWindow;
}

Minimap.prototype.getContentRootElement = function(contentWindow) {
    // https://developer.mozilla.org/en-US/docs/Mozilla_Quirks_Mode_Behavior
    // The scrollLeft, scrollTop, scrollWidth, and scrollHeight properties are
    // relative to BODY in quirks mode (instead of HTML)  (bug 211030).
    if (!contentWindow) {
        contentWindow = this.getContentWindow();
    }
    let contentDocument = contentWindow.document;

    if (contentDocument.compatMode == "BackCompat") {
        return contentDocument.body;
    } else {
        return contentDocument.documentElement;
    }
}

Minimap.prototype.wheelScrollMinimap = function(e) {
    // FIXME: obey firefox mousewheel prefs, including modifier keys ?
    let scroller = this.getScrollerElm(-1);
    if (!scroller) {
        return;
    }
    let top = scroller.offsetTop + (e.deltaY * 10);
    let left = scroller.offsetLeft + (e.deltaX * 10);
    this.absoluteScrollMinimap(top, left);
}

Minimap.prototype.clickScrollMinimap = function(e) {
    let scroller = this.getScrollerElm(-1);
    if (!scroller) {
        return;
    }
    let top = e.pageY - (scroller.offsetHeight / 2);
    let left = e.pageX - (scroller.offsetWidth / 2);
    this.absoluteScrollMinimap(top, left);
}

Minimap.prototype.absoluteScrollMinimap = function(top, left) {
    if (typeof this.ratiow === 'undefined' ||
        typeof this.ratioh === 'undefined') {
        // console.log('ratio undefined :(');
        return;
    }
    let contentRootElement = this.getContentRootElement();

    // Transform mouse position values in the sidebar in scroll position on
    // the target document
    top = Math.round(top / this.ratioh);
    left = Math.round(left / this.ratiow);

    // FIXME: constrain ? this doesn't seem to be necessary, but maybe there is
    // a performance gain, especially if we can determine whether we need to
    // adjust scrollTop/Left or not depending on the constrained values
    // FIXME: use page mod instead of accessing document properties directly ?
    contentRootElement.scrollTop = top;
    contentRootElement.scrollLeft = left;

    // Calling drawScroller() isn't necessary, since we listen on "scroll"
    // event on the document.
}

Minimap.prototype.getCanvasElm = function(index) {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let sidebarDocument = this.sidebar.browser.contentDocument;
    if (!sidebarDocument) {
        return null;
    }
    let canvas = sidebarDocument.getElementById('minimap');
    if (!canvas) {
        canvas = sidebarDocument.createElement('canvas');
        canvas.id = 'minimap';
        sidebarDocument.body.appendChild(canvas);
    }
    return canvas;
}

Minimap.prototype.getScrollerElm = function(index) {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let sidebarDocument = this.sidebar.browser.contentDocument;
    if (!sidebarDocument) {
        return null;
    }
    return sidebarDocument.getElementById('scroller');
}

Minimap.prototype.drawScroller = function() {
    // FIXME: watch resize on sidebar
    let scroller = this.getScrollerElm(-1);
    let canvas = this.getCanvasElm(-1);
    let sidebarDocument = this.sidebar.browser.contentDocument;

    if (!sidebarDocument || !scroller || !canvas || !canvas.width || !canvas.height) {
        // not ready yet
        // console.warn('drawScroller() called, but canvas has no dimensions yet');
        return;
    }

    // canvas width and height contain the real size of the document.
    // canvas is automatically resized by the browser, we need to find out
    // it's real dimensions, not the dimensions we set ourselves, we do that
    // using offsetWidth and offsetHeight
    let canvasRealHeight = canvas.offsetHeight;
    let canvasRealWidth = canvas.offsetWidth;
    this.ratiow = canvasRealWidth / canvas.width;
    this.ratioh = canvasRealHeight / canvas.height;

    // FIXME: use page mod instead of accessing document directly ?
    let contentRootElement = this.getContentRootElement();
    let width = Math.round(this.ratiow * contentRootElement.clientWidth);
    let height = Math.round(this.ratioh * contentRootElement.clientHeight);
    let top = Math.round(this.ratioh * contentRootElement.scrollTop);
    let left = Math.round(this.ratiow * contentRootElement.scrollLeft);

    // before drawing scroller, let's check whether we should move the canvas
    // or not.
    let sidebarHeight = sidebarDocument.documentElement.offsetHeight; // FIXME: cache this, not going to change unless we resize the window
    if (canvasRealHeight > sidebarHeight) {
        let scrollRatio = (contentRootElement.scrollTop) / (contentRootElement.scrollHeight - contentRootElement.clientHeight);
        let sidebarScrollTop = Math.round((canvasRealHeight - sidebarHeight) * scrollRatio);
        sidebarDocument.documentElement.scrollTop = sidebarScrollTop;
        /*
        console.log('Sidebar offsetHeight: ', sidebarHeight);
        console.log('Canvas offsetHeight:', canvasRealHeight);
        console.log('Canvas height:', canvas.height);
        console.log('Scroll ratio: ', scrollRatio);
        console.log('Scroll top (document): ', contentDocumentElement.scrollTop);
        console.log('Scroll top (asked): ', sidebarScrollTop);
        sidebarScrollTop = sidebarDocument.documentElement.scrollTop;
        console.log('Scroll top (result): ', sidebarScrollTop);
        */
    }

/*
    console.log('Document width x height: ', canvas.width, canvas.height);
    console.log('Minimap width x height: ', computedwith, computedheight);
    console.log('Content width x height: ', contentDocumentElement.clientWidth,
                                           contentDocumentElement.clientHeight);
    console.log('Scroller width x height: ', width, height);
    console.log('Scroller top x left: ', top, left);
*/
    scroller.style.width = width + 'px';
    scroller.style.height = height + 'px';
    scroller.style.top = top + 'px';
    scroller.style.left = left + 'px';
    scroller.style.display = 'block';
}

Minimap.prototype.drawMinimap = function() {
    let contentWindow = this.getContentWindow();
    let contentRootElement = this.getContentRootElement(contentWindow);
    let canvas = this.getCanvasElm(-1);
    if (!canvas) {
        return;
    }
    let left = 0;
    let top = 0;
    let width = contentRootElement.scrollWidth;
    let height = contentRootElement.scrollHeight;
    if (height < 10) {
        // Hack: arbitrary value, used to prevent drawing minimap on dummy
        // content
        return;
    }
    canvas.width = width;
    canvas.height = height;
    let ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, width, height);
    ctx.save();
    ctx.scale(1.0, 1.0);
    ctx.drawWindow(contentWindow, left, top, width, height, 'rgb(255,255,255)');
    ctx.restore();
    this.drawScroller();
}

exports.Minimap = Minimap;<commit_msg>Remove old debug comments<commit_after>const { getActiveTab } = require('tabs/utils');

function Minimap(sidebar) {
    var minimap = this;
    minimap.sidebar = sidebar;  // FIXME: will this leak when destroying windows ?
    let sidebarDocument = minimap.sidebar.browser.contentDocument;

    minimap.isdown = false;
    sidebarDocument.documentElement.addEventListener('mousedown', function(e) {
        minimap.isdown = true;
        minimap.clickScrollMinimap(e);
    });

    sidebarDocument.documentElement.addEventListener('wheel', function(e) {
        minimap.wheelScrollMinimap(e);
    });

    sidebarDocument.documentElement.addEventListener('mouseup', function(e) {
        minimap.isdown = false;
    });

    sidebarDocument.documentElement.addEventListener('mousemove', function(e) {
        if (minimap.isdown) {
            minimap.clickScrollMinimap(e);
        }
    });
};

Minimap.prototype.getContentWindow = function() {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let win = this.sidebar.window;
    let contentWindow = getActiveTab(win).linkedBrowser.contentWindow;
    // let index = win.gBrowser.getBrowserIndexForDocument(contentWindow.document);
    return contentWindow;
}

Minimap.prototype.getContentRootElement = function(contentWindow) {
    // https://developer.mozilla.org/en-US/docs/Mozilla_Quirks_Mode_Behavior
    // The scrollLeft, scrollTop, scrollWidth, and scrollHeight properties are
    // relative to BODY in quirks mode (instead of HTML)  (bug 211030).
    if (!contentWindow) {
        contentWindow = this.getContentWindow();
    }
    let contentDocument = contentWindow.document;

    if (contentDocument.compatMode == "BackCompat") {
        return contentDocument.body;
    } else {
        return contentDocument.documentElement;
    }
}

Minimap.prototype.wheelScrollMinimap = function(e) {
    // FIXME: obey firefox mousewheel prefs, including modifier keys ?
    let scroller = this.getScrollerElm(-1);
    if (!scroller) {
        return;
    }
    let top = scroller.offsetTop + (e.deltaY * 10);
    let left = scroller.offsetLeft + (e.deltaX * 10);
    this.absoluteScrollMinimap(top, left);
}

Minimap.prototype.clickScrollMinimap = function(e) {
    let scroller = this.getScrollerElm(-1);
    if (!scroller) {
        return;
    }
    let top = e.pageY - (scroller.offsetHeight / 2);
    let left = e.pageX - (scroller.offsetWidth / 2);
    this.absoluteScrollMinimap(top, left);
}

Minimap.prototype.absoluteScrollMinimap = function(top, left) {
    if (typeof this.ratiow === 'undefined' ||
        typeof this.ratioh === 'undefined') {
        // console.log('ratio undefined :(');
        return;
    }
    let contentRootElement = this.getContentRootElement();

    // Transform mouse position values in the sidebar in scroll position on
    // the target document
    top = Math.round(top / this.ratioh);
    left = Math.round(left / this.ratiow);

    // FIXME: constrain ? this doesn't seem to be necessary, but maybe there is
    // a performance gain, especially if we can determine whether we need to
    // adjust scrollTop/Left or not depending on the constrained values
    // FIXME: use page mod instead of accessing document properties directly ?
    contentRootElement.scrollTop = top;
    contentRootElement.scrollLeft = left;

    // Calling drawScroller() isn't necessary, since we listen on "scroll"
    // event on the document.
}

Minimap.prototype.getCanvasElm = function(index) {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let sidebarDocument = this.sidebar.browser.contentDocument;
    if (!sidebarDocument) {
        return null;
    }
    let canvas = sidebarDocument.getElementById('minimap');
    if (!canvas) {
        canvas = sidebarDocument.createElement('canvas');
        canvas.id = 'minimap';
        sidebarDocument.body.appendChild(canvas);
    }
    return canvas;
}

Minimap.prototype.getScrollerElm = function(index) {
    // FIXME: this needs to be changed when working on background tabs
    // support (generate minimap even for non-active tab)
    let sidebarDocument = this.sidebar.browser.contentDocument;
    if (!sidebarDocument) {
        return null;
    }
    return sidebarDocument.getElementById('scroller');
}

Minimap.prototype.drawScroller = function() {
    // FIXME: watch resize on sidebar
    let scroller = this.getScrollerElm(-1);
    let canvas = this.getCanvasElm(-1);
    let sidebarDocument = this.sidebar.browser.contentDocument;

    if (!sidebarDocument || !scroller || !canvas || !canvas.width || !canvas.height) {
        // not ready yet
        // console.warn('drawScroller() called, but canvas has no dimensions yet');
        return;
    }

    // canvas width and height contain the real size of the document.
    // canvas is automatically resized by the browser, we need to find out
    // it's real dimensions, not the dimensions we set ourselves, we do that
    // using offsetWidth and offsetHeight
    let canvasRealHeight = canvas.offsetHeight;
    let canvasRealWidth = canvas.offsetWidth;
    this.ratiow = canvasRealWidth / canvas.width;
    this.ratioh = canvasRealHeight / canvas.height;

    // FIXME: use page mod instead of accessing document directly ?
    let contentRootElement = this.getContentRootElement();
    let width = Math.round(this.ratiow * contentRootElement.clientWidth);
    let height = Math.round(this.ratioh * contentRootElement.clientHeight);
    let top = Math.round(this.ratioh * contentRootElement.scrollTop);
    let left = Math.round(this.ratiow * contentRootElement.scrollLeft);

    // before drawing scroller, let's check whether we should move the canvas
    // or not.
    let sidebarHeight = sidebarDocument.documentElement.offsetHeight; // FIXME: cache this, not going to change unless we resize the window
    if (canvasRealHeight > sidebarHeight) {
        let scrollRatio = (contentRootElement.scrollTop) / (contentRootElement.scrollHeight - contentRootElement.clientHeight);
        let sidebarScrollTop = Math.round((canvasRealHeight - sidebarHeight) * scrollRatio);
        sidebarDocument.documentElement.scrollTop = sidebarScrollTop;
    }
    scroller.style.width = width + 'px';
    scroller.style.height = height + 'px';
    scroller.style.top = top + 'px';
    scroller.style.left = left + 'px';
    scroller.style.display = 'block';
}

Minimap.prototype.drawMinimap = function() {
    let contentWindow = this.getContentWindow();
    let contentRootElement = this.getContentRootElement(contentWindow);
    let canvas = this.getCanvasElm(-1);
    if (!canvas) {
        return;
    }
    let left = 0;
    let top = 0;
    let width = contentRootElement.scrollWidth;
    let height = contentRootElement.scrollHeight;
    if (height < 10) {
        // Hack: arbitrary value, used to prevent drawing minimap on dummy
        // content
        return;
    }
    canvas.width = width;
    canvas.height = height;
    let ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, width, height);
    ctx.save();
    ctx.scale(1.0, 1.0);
    ctx.drawWindow(contentWindow, left, top, width, height, 'rgb(255,255,255)');
    ctx.restore();
    this.drawScroller();
}

exports.Minimap = Minimap;<|endoftext|>


<commit_before>require('./Constraint');
lib.DistanceConstraint = DistanceConstraint;
function DistanceConstraint(distance, a, b) {
  this._indices = new Uint16Array(2 * 3);
  this.setDistance(distance);
  this.setIndices(a, b);
}

DistanceConstraint.prototype = Object.create(lib.Constraint.prototype);
DistanceConstraint.prototype.setIndices = lib.Constraint.setIndices(3);

DistanceConstraint.prototype.setDistance = function (distance) {
  this._distance2 = distance * distance;
};

DistanceConstraint.prototype.applyConstraint = function (p0) {
  var ii = this._indices;
  var ax = ii[0], ay = ii[1], az = ii[2];
  var bx = ii[3], by = ii[4], bz = ii[5];

  var dx = p0[bx] - p0[ax];
  var dy = p0[by] - p0[ay];
  var dz = p0[bz] - p0[az];

  if (!(dx && dy && dz)) {
    dx = dy = dz = 0.1;
  }

  var dist2 = this._distance2;
  var len2 = dx * dx + dy * dy + dz * dz;
  var diff = dist2 / (len2 + dist2) - 0.5;

  dx *= diff;
  dy *= diff;
  dz *= diff;

  p0[ax] -= dx;
  p0[ay] -= dy;
  p0[az] -= dz;

  p0[bx] += dx;
  p0[by] += dy;
  p0[bz] += dz;
};
<commit_msg>Fix zero distance evaluation<commit_after>require('./Constraint');
lib.DistanceConstraint = DistanceConstraint;
function DistanceConstraint(distance, a, b) {
  this._indices = new Uint16Array(2 * 3);
  this.setDistance(distance);
  this.setIndices(a, b);
}

DistanceConstraint.prototype = Object.create(lib.Constraint.prototype);
DistanceConstraint.prototype.setIndices = lib.Constraint.setIndices(3);

DistanceConstraint.prototype.setDistance = function (distance) {
  this._distance2 = distance * distance;
};

DistanceConstraint.prototype.applyConstraint = function (p0) {
  var ii = this._indices;
  var ax = ii[0], ay = ii[1], az = ii[2];
  var bx = ii[3], by = ii[4], bz = ii[5];

  var dx = p0[bx] - p0[ax];
  var dy = p0[by] - p0[ay];
  var dz = p0[bz] - p0[az];

  if (!(dx || dy || dz)) {
    dx = dy = dz = 0.1;
  }

  var dist2 = this._distance2;
  var len2 = dx * dx + dy * dy + dz * dz;
  var diff = dist2 / (len2 + dist2) - 0.5;

  dx *= diff;
  dy *= diff;
  dz *= diff;

  p0[ax] -= dx;
  p0[ay] -= dy;
  p0[az] -= dz;

  p0[bx] += dx;
  p0[by] += dy;
  p0[bz] += dz;
};
<|endoftext|>


<commit_before>function MockImg(filePath) {
};

MockImg.prototype.size = function(fn) {
  fn(null, {});
};

MockImg.prototype.toBuffer = function(type, fn) {
  fn(null, new Buffer(1));
};

MockImg.prototype.resize = function(w, h) {
  return this;
};

MockImg.prototype.crop = function(w, h, x, y) {
  return this;
};

MockImg.prototype.format = function(fn) {
  var formats = ['jpg', 'jpeg', 'png'];
  var format = formats[Math.round(Math.random() * (formats.length - 1))];
  fn(null, format);
};

MockImg.prototype.quality = function(max) {
  return this;
};

MockImg.prototype.flatten = function() {
  return this;
};

MockImg.prototype.scene = function() {
  return this;
};

MockImg.prototype.coalesce = function() {
  return this;
};

module.exports = function(filePath) {
  return new MockImg(filePath);
};
<commit_msg>remove cc warnings<commit_after>function MockImg() {}

MockImg.prototype.size = function(fn) {
  fn(null, {});
};

MockImg.prototype.toBuffer = function(type, fn) {
  type = 'mock';
  fn(null, new Buffer(1));
};

MockImg.prototype.resize = function(w, h) {
  w = 0;
  h = 0;
  return this;
};

MockImg.prototype.crop = function(w, h, x, y) {
  x = 0;
  h = 0;
  x = 0;
  y = 0;
  return this;
};

MockImg.prototype.format = function(fn) {
  var formats = ['jpg', 'jpeg', 'png'];
  var format = formats[Math.round(Math.random() * (formats.length - 1))];
  fn(null, format);
};

MockImg.prototype.quality = function(max) {
  max = 0;
  return this;
};

MockImg.prototype.flatten = function() {
  return this;
};

MockImg.prototype.scene = function() {
  return this;
};

MockImg.prototype.coalesce = function() {
  return this;
};

module.exports = function(filePath) {
  return new MockImg(filePath);
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { api } from '../../data'
import { Field, Submit, Base, Subheading } from '../components/Forms'
import Button from '../components/Button'
import LoadingAnimation from '../components/LoadingAnimation'
import theme, { colors, mx } from '../theme'
import { withFormik } from 'formik'
import yup from 'yup'
import fetch from 'unfetch'

const id = () => {
  const pairs = window.location.search.split(/\?|&/)
  for (var i = 0; i < pairs.length; i++) {
    let pair = pairs[i]
    let k = pair.split('=')[0]
    let v = pair.split('=')[1]
    if (k === 'id') {
      return parseInt(v)
    }
  }
}
const authToken = () => (
  window.localStorage.getItem('authToken')
)
const formToObj = form => {
  var obj = {}
  const formData = new FormData(form)
  formData.forEach((v, k) => {
    obj[k] = v
  })
  return obj
}
const InnerForm = ({
  values,
  errors,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting,
  saveDraft = (e) => {
    const draftButton = e.target
    draftButton.value = 'Saving...'
    draftButton.disabled = true
    const data = formToObj(e.target.form)
    fetch(`${api}/v1/club_applications/${id()}`, {
      method: 'PATCH',
      headers: {
        'Authorization': `Bearer ${authToken()}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    })
      .then(res => (res.json()))
      .then(json => {
        draftButton.value = 'Save as draft'
        draftButton.disabled = false
      })
      .catch(e => {
        alert(e)
        draftButton.value = 'Save as draft'
        draftButton.disabled = false
      })
  },
  inviteLeader = () => {
    const leaderInvite = window.document.querySelector('#leader_invite')
    const data = {email: leaderInvite.value}
    const schema = yup.object().shape({
      email: yup.string().required().email()
    })

    schema
      .validate(data)
      .then(data => {
        fetch(`${api}/v1/club_applications/${id()}/add_applicant`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${authToken()}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(data)
        })
          .then(res => (res.json()))
          .then(json => {
            alert(`Invite sent to ${data.email}`)
            leaderInvite.value = ''
          })
          .catch(e => {alert(e)})
      })
      .catch(e => {alert(e)})
  }
}) => (
  <Base is="form" onSubmit={handleSubmit}>
    <Subheading>School</Subheading>
    <Field name="high_school_name"
           label="Name of high school"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_name}
           error={touched.high_school_name && errors.high_school_name}
    />
    <Field name="high_school_url"
           label="Link to your high school's website, if any"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_url}
           error={touched.high_school_url && errors.high_school_url}
    />
    <Field name="high_school_type"
           label="Type of school"
           type="select"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_type || 'select'}
           error={touched.high_school_type && errors.high_school_type}
    >
      <option disabled value="select">Select One</option>
      <option value="0">Public</option>
      <option value="1">Private</option>
      <option value="2">Charter</option>
    </Field>
    <Field name="high_school_address"
           label="High school's full address"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_address}
           error={touched.high_school_address && errors.high_school_address}
           type="textarea" />
    <Subheading>Leaders</Subheading>

      {values.applicant_profiles.map((profile, index) => (

{profile.applicant.email}

      ))}

    <Field label="Email address of co-leader" id="leader_invite" />
    <Button onClick={inviteLeader}>Add co-leader</Button>
    <Field name="leaders_video_url"
           label="Please enter the URL of a 1 minute unlisted (not private) YouTube video introducing the leaders"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_video_url}
           error={touched.leaders_video_url && errors.leaders_video_url}
    />
    <Field name="leaders_interesting_project"
           label="Please tell us about an interesting project, preferably outside of class, that two or more of you created together. Include URLs if possible."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_interesting_project}
           error={touched.leaders_interesting_project && errors.leaders_interesting_project}
           type="textarea" />
    <Field name="leaders_team_origin_story"
           label="How long have you known your other club leaders and how did you meet?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_team_origin_story}
           error={touched.leaders_team_origin_story && errors.leaders_team_origin_story}
           type="textarea" />
    <Subheading>Progress</Subheading>
    <Field name="progress_general"
           label="How far along are you in starting your club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_general}
           error={touched.progress_general && errors.progress_general}
           type="textarea" />
    <Field name="progress_student_interest"
           label="Have you already polled for interest at your school? Are students interested? If you've already had meetings, how many people came?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_student_interest}
           error={touched.progress_student_interest && errors.progress_student_interest}
           type="textarea" />
    <Field name="progress_meeting_yet"
           label="Have you begun meeting yet? We encourage you to not begin meeting until we accept you."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_meeting_yet}
           error={touched.progress_meeting_yet && errors.progress_meeting_yet}
           type="textarea" />
    <Subheading>Idea</Subheading>
    <Field name="idea_why"
           label="Why did you decide to start a Hack Club? Have you ran anything like a Hack Club before? Why do you think the club is going to work?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_why}
           error={touched.idea_why && errors.idea_why}
           type="textarea" />
    <Field name="idea_other_coding_clubs"
           label="Has your school had coding clubs before? What's going to be new about your Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_other_coding_clubs}
           error={touched.idea_other_coding_clubs && errors.idea_other_coding_clubs}
           type="textarea" />
    <Field name="idea_other_general_clubs"
           label="What other clubs exist at your school? Why will you be just as successful, if not more, than them?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_other_general_clubs}
           error={touched.idea_other_general_clubs && errors.idea_other_general_clubs}
           type="textarea" />
    <Subheading>Formation</Subheading>
    <Field name="formation_registered"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.formation_registered}
           error={touched.formation_registered && errors.formation_registered}
           label="Have you already registerd your club with your school?"
    />
    <Field name="formation_misc"
           label="Please provide any other relevant information about the structure or formation of the club."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.formation_misc}
           error={touched.formation_misc && errors.formation_misc}
           type="textarea" />
    <Subheading>Other</Subheading>
    <Field name="other_surprising_or_amusing_discovery"
           label="What is something surprising or amusing you discovered?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.other_surprising_or_amusing_discovery}
           error={touched.other_surprising_or_amusing_discovery && errors.other_surprising_or_amusing_discovery}
           type="textarea" />
    <Subheading>Curious</Subheading>
    <Field name="curious_what_convinced"
           label="What convinced you to start a Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.curious_what_convinced}
           error={touched.curious_what_convinced && errors.curious_what_convinced}
           type="textarea" />
    <Field name="curious_how_did_hear"
           label="How did you hear about Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.curious_how_did_hear}
           error={touched.curious_how_did_hear && errors.curious_how_did_hear}
           type="textarea" />
    <Submit
      onClick={saveDraft}
      value="Save as draft"
    />

    {/* TODO: Add a submit button that submits instead of saving a draft */}
    {/* <Submit
        disabled={isSubmitting || !isValid}
        onClick={handleSubmit}
        value="Submit"
        /> */}
  </Base>
)

const ClubForm = withFormik({
  mapPropsToValues: params => ( {...params} ),
  enableReinitialize: true,
  displayName: 'ClubForm',
  handleSubmit: (values, {props, setSubmitting, setErrors}) => {
    // this will submit as a final draft
  }
})(InnerForm)

export default class extends Component {
  constructor(props) {
    super(props)

    this.state = {
      status: 'loading',
      formFields: null
    }
  }

  componentDidMount() {
    fetch(`${api}/v1/club_applications/${id()}`, {
      method: 'GET',
      headers: { 'Authorization': `Bearer ${authToken()}`, },
    })
      .then(res => {
        if (res.ok) {
          return res.json()
        } else {
          throw res
        }})
      .then(json => {
        this.setState({
          status: 'loaded',
          formFields: json
        })
      })
      .catch(e => {alert(e)})
  }

  render() {
    const { status, formFields } = this.state

    if (status === 'loading' || formFields === null) {
      return(<LoadingAnimation />)
    } else {
      return(<ClubForm {...formFields} />)
    }
  }
}
<commit_msg>Refactor onClick functions in club application form<commit_after>import React, { Component } from 'react'
import { api } from '../../data'
import { Field, Submit, Base, Subheading } from '../components/Forms'
import Button from '../components/Button'
import LoadingAnimation from '../components/LoadingAnimation'
import theme, { colors, mx } from '../theme'
import { withFormik } from 'formik'
import yup from 'yup'
import fetch from 'unfetch'

const id = () => {
  const pairs = window.location.search.split(/\?|&/)
  for (var i = 0; i < pairs.length; i++) {
    let pair = pairs[i]
    let k = pair.split('=')[0]
    let v = pair.split('=')[1]
    if (k === 'id') {
      return parseInt(v)
    }
  }
}
const authToken = () => (
  window.localStorage.getItem('authToken')
)
const formToObj = form => {
  var obj = {}
  const formData = new FormData(form)
  formData.forEach((v, k) => {
    obj[k] = v
  })
  return obj
}
function saveDraftFunction() {
  return (e) => {
    const draftButton = e.target
    draftButton.value = 'Saving...'
    draftButton.disabled = true
    const data = formToObj(e.target.form)
    fetch(`${api}/v1/club_applications/${id()}`, {
      method: 'PATCH',
      headers: {
        'Authorization': `Bearer ${authToken()}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    })
      .then(res => (res.json()))
      .then(json => {
        draftButton.value = 'Save as draft'
        draftButton.disabled = false
      })
      .catch(e => {
        alert(e)
        draftButton.value = 'Save as draft'
        draftButton.disabled = false
      })
  }
}
function inviteLeaderFunction() {
  return () => {
    const leaderInvite = window.document.querySelector('#leader_invite')
    const data = {email: leaderInvite.value}
    const schema = yup.object().shape({
      email: yup.string().required().email()
    })

    schema
      .validate(data)
      .then(data => {
        fetch(`${api}/v1/club_applications/${id()}/add_applicant`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${authToken()}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(data)
        })
          .then(res => (res.json()))
          .then(json => {
            alert(`Invite sent to ${data.email}. Refresh for their email to be added to the list.`)
            leaderInvite.value = ''
          })
          .catch(e => {alert(e)})
      })
      .catch(e => {alert(e)})
  }
}

const InnerForm = ({
  values,
  errors,
  touched,
  handleChange,
  handleBlur,
  handleSubmit,
  isSubmitting,
  saveDraft = saveDraftFunction(),
  inviteLeader = inviteLeaderFunction()
}) => (
  <Base is="form" onSubmit={handleSubmit}>
    <Subheading>School</Subheading>
    <Field name="high_school_name"
           label="Name of high school"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_name}
           error={touched.high_school_name && errors.high_school_name}
    />
    <Field name="high_school_url"
           label="Link to your high school's website, if any"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_url}
           error={touched.high_school_url && errors.high_school_url}
    />
    <Field name="high_school_type"
           label="Type of school"
           type="select"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_type || 'select'}
           error={touched.high_school_type && errors.high_school_type}
    >
      <option disabled value="select">Select One</option>
      <option value="0">Public</option>
      <option value="1">Private</option>
      <option value="2">Charter</option>
    </Field>
    <Field name="high_school_address"
           label="High school's full address"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.high_school_address}
           error={touched.high_school_address && errors.high_school_address}
           type="textarea" />
    <Subheading>Leaders</Subheading>

      {values.applicant_profiles.map((profile, index) => (

{profile.applicant.email}

      ))}

    <Field label="Email address of co-leader" id="leader_invite" />
    <Button onClick={inviteLeader}>Add co-leader</Button>
    <Field name="leaders_video_url"
           label="Please enter the URL of a 1 minute unlisted (not private) YouTube video introducing the leaders"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_video_url}
           error={touched.leaders_video_url && errors.leaders_video_url}
    />
    <Field name="leaders_interesting_project"
           label="Please tell us about an interesting project, preferably outside of class, that two or more of you created together. Include URLs if possible."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_interesting_project}
           error={touched.leaders_interesting_project && errors.leaders_interesting_project}
           type="textarea" />
    <Field name="leaders_team_origin_story"
           label="How long have you known your other club leaders and how did you meet?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.leaders_team_origin_story}
           error={touched.leaders_team_origin_story && errors.leaders_team_origin_story}
           type="textarea" />
    <Subheading>Progress</Subheading>
    <Field name="progress_general"
           label="How far along are you in starting your club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_general}
           error={touched.progress_general && errors.progress_general}
           type="textarea" />
    <Field name="progress_student_interest"
           label="Have you already polled for interest at your school? Are students interested? If you've already had meetings, how many people came?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_student_interest}
           error={touched.progress_student_interest && errors.progress_student_interest}
           type="textarea" />
    <Field name="progress_meeting_yet"
           label="Have you begun meeting yet? We encourage you to not begin meeting until we accept you."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.progress_meeting_yet}
           error={touched.progress_meeting_yet && errors.progress_meeting_yet}
           type="textarea" />
    <Subheading>Idea</Subheading>
    <Field name="idea_why"
           label="Why did you decide to start a Hack Club? Have you ran anything like a Hack Club before? Why do you think the club is going to work?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_why}
           error={touched.idea_why && errors.idea_why}
           type="textarea" />
    <Field name="idea_other_coding_clubs"
           label="Has your school had coding clubs before? What's going to be new about your Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_other_coding_clubs}
           error={touched.idea_other_coding_clubs && errors.idea_other_coding_clubs}
           type="textarea" />
    <Field name="idea_other_general_clubs"
           label="What other clubs exist at your school? Why will you be just as successful, if not more, than them?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.idea_other_general_clubs}
           error={touched.idea_other_general_clubs && errors.idea_other_general_clubs}
           type="textarea" />
    <Subheading>Formation</Subheading>
    <Field name="formation_registered"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.formation_registered}
           error={touched.formation_registered && errors.formation_registered}
           label="Have you already registerd your club with your school?"
    />
    <Field name="formation_misc"
           label="Please provide any other relevant information about the structure or formation of the club."
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.formation_misc}
           error={touched.formation_misc && errors.formation_misc}
           type="textarea" />
    <Subheading>Other</Subheading>
    <Field name="other_surprising_or_amusing_discovery"
           label="What is something surprising or amusing you discovered?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.other_surprising_or_amusing_discovery}
           error={touched.other_surprising_or_amusing_discovery && errors.other_surprising_or_amusing_discovery}
           type="textarea" />
    <Subheading>Curious</Subheading>
    <Field name="curious_what_convinced"
           label="What convinced you to start a Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.curious_what_convinced}
           error={touched.curious_what_convinced && errors.curious_what_convinced}
           type="textarea" />
    <Field name="curious_how_did_hear"
           label="How did you hear about Hack Club?"
           onChange={handleChange}
           onBlur={handleBlur}
           value={values.curious_how_did_hear}
           error={touched.curious_how_did_hear && errors.curious_how_did_hear}
           type="textarea" />
    <Submit
      onClick={saveDraft}
      value="Save as draft"
    />

    {/* TODO: Add a submit button that submits instead of saving a draft */}
    {/* <Submit
        disabled={isSubmitting || !isValid}
        onClick={handleSubmit}
        value="Submit"
        /> */}
  </Base>
)

const ClubForm = withFormik({
  mapPropsToValues: params => ( {...params} ),
  enableReinitialize: true,
  displayName: 'ClubForm',
  handleSubmit: (values, {props, setSubmitting, setErrors}) => {
    // this will submit as a final draft
  }
})(InnerForm)

export default class extends Component {
  constructor(props) {
    super(props)

    this.state = {
      status: 'loading',
      formFields: null
    }
  }

  componentDidMount() {
    fetch(`${api}/v1/club_applications/${id()}`, {
      method: 'GET',
      headers: { 'Authorization': `Bearer ${authToken()}`, },
    })
      .then(res => {
        if (res.ok) {
          return res.json()
        } else {
          throw res
        }})
      .then(json => {
        this.setState({
          status: 'loaded',
          formFields: json
        })
      })
      .catch(e => {alert(e)})
  }

  render() {
    const { status, formFields } = this.state

    if (status === 'loading' || formFields === null) {
      return(<LoadingAnimation />)
    } else {
      return(<ClubForm {...formFields} />)
    }
  }
}
<|endoftext|>


<commit_before>// Fine Uploader's modules
//
// shamelessly inspired by:
// https://github.com/angular/angular.js/blob/master/angularFiles.js

fineUploaderModules = {
  "fuSrcCore": [
    "./client/js/util.js",
    "./client/js/version.js",
    "./client/js/features.js",
    "./client/js/promise.js",
    "./client/js/button.js",
    "./client/js/upload-data.js",
    "./client/js/uploader.basic.api.js",
    "./client/js/uploader.basic.js",
    "./client/js/uploader.api.js",
    "./client/js/uploader.js",
    "./client/js/ajax.requester.js",
    "./client/js/handler.base.js",
    "./client/js/handler.xhr.api.js",
    "./client/js/handler.form.api.js"
  ],
  "fuSrcTraditional": [
    "@fuSrcCore",
    "./client/js/traditional/handler.form.js",
    "./client/js/traditional/handler.xhr.js"
  ],
  "fuSrcS3": [
    "@fuSrcCore",
    "./client/js/s3/util.js",
    "./client/js/s3/uploader.basic.js",
    "./client/js/s3/uploader.js",
    "./client/js/s3/signature.ajax.requester.js",
    "./client/js/s3/uploadsuccess.ajax.requester.js",
    "./client/js/s3/multipart.initiate.ajax.requester.js",
    "./client/js/s3/multipart.complete.ajax.requester.js",
    "./client/js/s3/multipart.abort.ajax.requester.js",
    "./client/js/s3/handler.xhr.js",
    "./client/js/s3/handler.form.js",
    "./client/js/s3/jquery-plugin.js"
  ],
  "fuSrcJquery": [
    "./client/js/jquery-plugin.js",
    "./client/js/jquery-dnd.js"
  ],
  "fuSrcAll": [
    "@fuSrcTraditional",
    "@fuSrcS3",
    "@fuSrcJquery"
  ],
  "fuSrcModules": [
    "./client/js/paste.js",
    "./client/js/dnd.js",
    "./client/js/deletefile.ajax.requester.js",
    "./client/js/window.receive.message.js"
  ],
  "fuUiModules": [
    "./client/js/templating.js",
    "./client/js/ui.handler.events.js",
    "./client/js/ui.handler.click.drc.js",
    "./client/js/ui.handler.edit.filename.js",
    "./client/js/ui.handler.click.filename.js",
    "./client/js/ui.handler.focusin.filenameinput.js",
    "./client/js/ui.handler.focus.filenameinput.js"
  ],
  "fuIframeXssResponse": [
    "./client/js/iframe.xss.response.js"
  ],
  "fuExtra": [
    "./client/loading.gif",
    "./client/processing.gif",
    "./client/fineuploader.css",
    "./client/edit.gif",
    "./README.md",
    "./LICENSE"
  ],
  "versioned": [
    "package.json",
    "fineuploader.jquery.json",
    "./client/js/version.js",
    "bower.json",
    "README.md"
  ],
  "fuUnit": [
    "./test/static/helpme.js",
    "./test/unit/*.js",
    "./test/unit/s3/*.js"
  ],
  "fuFunctional": [
    "./test/functional/**/*.coffee"
  ],
  "karmaModules": [
    "./test/static/karma-runner.js",
    "./test/_vendor/assert/assert.js",
    "./test/_vendor/jquery/jquery.js",
    "./test/_vendor/jquery.simulate/jquery.simulate.js",
    "./test/_vendor/json2/json2.js",
    "./test/_vendor/purl/purl.js"
  ],

};

if (exports) {
  exports.modules = fineUploaderModules;
  exports.mergeModules = function() {
    var files = [];

    Array.prototype.slice.call(arguments, 0).forEach(function(filegroup) {
      fineUploaderModules[filegroup].forEach(function(file) {
        // replace @ref
        var match = file.match(/^\@(.*)/);
        if (match) {
            files = files.concat(fineUploaderModules[match[1]]);
        } else {
          files.push(file);
        }
      });
    });

    return files;
  };
}
<commit_msg>fix(lib/modules.js): syntax error<commit_after>// Fine Uploader's modules
//
// shamelessly inspired by:
// https://github.com/angular/angular.js/blob/master/angularFiles.js

fineUploaderModules = {
  "fuSrcCore": [
    "./client/js/util.js",
    "./client/js/version.js",
    "./client/js/features.js",
    "./client/js/promise.js",
    "./client/js/button.js",
    "./client/js/upload-data.js",
    "./client/js/uploader.basic.api.js",
    "./client/js/uploader.basic.js",
    "./client/js/uploader.api.js",
    "./client/js/uploader.js",
    "./client/js/ajax.requester.js",
    "./client/js/handler.base.js",
    "./client/js/handler.xhr.api.js",
    "./client/js/handler.form.api.js"
  ],
  "fuSrcTraditional": [
    "@fuSrcCore",
    "./client/js/traditional/handler.form.js",
    "./client/js/traditional/handler.xhr.js"
  ],
  "fuSrcS3": [
    "@fuSrcCore",
    "./client/js/s3/util.js",
    "./client/js/s3/uploader.basic.js",
    "./client/js/s3/uploader.js",
    "./client/js/s3/signature.ajax.requester.js",
    "./client/js/s3/uploadsuccess.ajax.requester.js",
    "./client/js/s3/multipart.initiate.ajax.requester.js",
    "./client/js/s3/multipart.complete.ajax.requester.js",
    "./client/js/s3/multipart.abort.ajax.requester.js",
    "./client/js/s3/handler.xhr.js",
    "./client/js/s3/handler.form.js",
    "./client/js/s3/jquery-plugin.js"
  ],
  "fuSrcJquery": [
    "./client/js/jquery-plugin.js",
    "./client/js/jquery-dnd.js"
  ],
  "fuSrcAll": [
    "@fuSrcTraditional",
    "@fuSrcS3",
    "@fuSrcJquery"
  ],
  "fuSrcModules": [
    "./client/js/paste.js",
    "./client/js/dnd.js",
    "./client/js/deletefile.ajax.requester.js",
    "./client/js/window.receive.message.js"
  ],
  "fuUiModules": [
    "./client/js/templating.js",
    "./client/js/ui.handler.events.js",
    "./client/js/ui.handler.click.drc.js",
    "./client/js/ui.handler.edit.filename.js",
    "./client/js/ui.handler.click.filename.js",
    "./client/js/ui.handler.focusin.filenameinput.js",
    "./client/js/ui.handler.focus.filenameinput.js"
  ],
  "fuIframeXssResponse": [
    "./client/js/iframe.xss.response.js"
  ],
  "fuExtra": [
    "./client/loading.gif",
    "./client/processing.gif",
    "./client/fineuploader.css",
    "./client/edit.gif",
    "./README.md",
    "./LICENSE"
  ],
  "versioned": [
    "package.json",
    "fineuploader.jquery.json",
    "./client/js/version.js",
    "bower.json",
    "README.md"
  ],
  "fuUnit": [
    "./test/static/helpme.js",
    "./test/unit/*.js",
    "./test/unit/s3/*.js"
  ],
  "fuFunctional": [
    "./test/functional/**/*.coffee"
  ],
  "karmaModules": [
    "./test/static/karma-runner.js",
    "./test/_vendor/assert/assert.js",
    "./test/_vendor/jquery/jquery.js",
    "./test/_vendor/jquery.simulate/jquery.simulate.js",
    "./test/_vendor/json2/json2.js",
    "./test/_vendor/purl/purl.js"
  ]

};

if (exports) {
  exports.modules = fineUploaderModules;
  exports.mergeModules = function() {
    var files = [];

    Array.prototype.slice.call(arguments, 0).forEach(function(filegroup) {
      fineUploaderModules[filegroup].forEach(function(file) {
        // replace @ref
        var match = file.match(/^\@(.*)/);
        if (match) {
            files = files.concat(fineUploaderModules[match[1]]);
        } else {
          files.push(file);
        }
      });
    });

    return files;
  };
}
<|endoftext|>


<commit_before>//@flow
import React from 'react';
import {
  View,
  InteractionManager,
  Dimensions,
  Platform,
  Alert,
} from 'react-native';
import {Actions} from 'react-native-router-flux';
import Spinner from 'react-native-spinkit';
import { Container,
 Navbar } from 'navbar-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
var MessageBarManager = require('react-native-message-bar').MessageBarManager;

import Item from './Components/Item';
import {fetchListFromDB,fetchListFromNetwork,updateListOrder,updateLastRead} from '../../ducks/directory';
import {fetch} from '../../ducks/bookshelf';

class Directory extends React.Component {

  componentWillMount() {
    this.props.fetchListFromDB(this.props.novel);

    // MessageBarManager.registerMessageBar(this.refs.alert);
  }
  // componentWillUnmount() {
  //   // Remove the alert located on this master page from the manager
  //   MessageBarManager.unregisterMessageBar();
  // }
  componentDidMount() {
    this.props.fetchListFromNetwork(this.props.novel);

    // MessageBarManager.showAlert({
    //   title: 'Your alert title goes here',
    //   message: 'Your alert message goes here',
    //   alertType: 'success',
    //   // See Properties section for full customization
    //   // Or check `index.ios.js` or `index.android.js` for a complete example
    // });
  }

  handleSwitchStar = ()=>{
    realmFactory().write(()=>{
      this.props.novel.star = !this.props.novel.star;
      this.props.novel.starAt = new Date();
      this.forceUpdate();
      //fetch list
      this.props.fetchNovels();
    });
  }

  handleSwitchOrder = ()=>{
    this.props.updateListOrder();
  }

  handleClickArticle = (article:Article,rowIndex:number)=>{
    let index = parseInt(rowIndex);
    if(this.props.params.get('order') == 'desc'){
      index = this.props.params.get('directory').size - index -1;
    }
    InteractionManager.runAfterInteractions(()=>{
      realmFactory().write(()=>{
        this.props.novel.lastReadIndex = index;
        this.props.novel.lastReadTitle = article.get('title');
        this.props.updateLastRead(index);
        this.forceUpdate();
      });
    });

    Actions.reader({
      novel:this.props.novel,
      directory:this.props.params.get('directory'),
      index
    });

  }

  lastScrollIndex = 0;
  scrollTo=(index)=>{
    if(this._scrollView ){
      if(index<0){
        index = 0;
      }
      InteractionManager.runAfterInteractions(() => {
        if(this._scrollView.scrollTo){
          var {height, width} = Dimensions.get('window');
          var rowMargin = height/49/2 - 2;
          if (index>rowMargin) {
            index -= rowMargin;
          }
          this._scrollView.scrollTo({y:index*49,animated:false});
        }
      });
      this.lastScrollIndex = index;
    }
  };

  getCurrentScrollIndex=(props = this.props)=>{
    if(props.params.get('order') == 'desc'){
      return props.params.get('directory').size-props.params.get('lastReadIndex')-3;
    }else{
      return props.params.get('lastReadIndex');
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.novel.directoryUrl!=this.props.novel.directoryUrl) {
      this.props.fetchListFromDB(nextProps.novel);
    }else if( nextProps.params.get('lastReadIndex')!=this.props.params.get('lastReadIndex')){
      let index = this.getCurrentScrollIndex(nextProps);
      if(Math.abs(index-this.lastScrollIndex)>=5){
        this.scrollTo(index);
      }
    }
  }

  _scrollView;
  render() {
    let self = this;
    let arrowLabel = '正序';
    let containerParams = {};

    if (this.props.params.get('fetching')) {
      containerParams.loading={
        styleContainer:{
          // marginTop:Platform.OS == 'ios'?64:40,
          backgroundColor:'rgba(102,102,102,.5)'
        },
        coverNavbar:false
      }
      containerParams.data = [];
    }else{

      let directory = this.props.params.get('directory');
      if (this.props.params.get('order') == 'desc') {
        directory = directory.reverse();
        arrowLabel = '逆序';
      }
      containerParams.data=directory.toArray();
    }

    containerParams.row= (rowData,_,rowID)=>{
      return <Item onPress={self.handleClickArticle.bind(null,rowData,rowID)} item={rowData}/>;
    }
    containerParams.type="list";
    containerParams.enableEmptySections=true;
    containerParams.initialListSize=100;
    containerParams.pageSize=200;
    containerParams.onEndReachedThreshold=0;
    containerParams.scrollRenderAheadDistance=1000;
    containerParams.contentRef = (_scrollView)=>{
      this._scrollView=_scrollView
    };

    let starIcon = "star-o";
    if(this.props.novel.star){
      starIcon = "star";
    }
    return (
      <Container
      {...containerParams}
      >
          <Navbar
              title={this.props.novel.title}
              left={{
                  icon: "ios-arrow-back",
                  label: "返回",
                  onPress: ()=>{
                    if (!this.props.novel.star) {
                      Alert.alert(
                        '提醒',
                        '未加入收藏,是否现在加入收藏?',
                        [
                          {text: '不', onPress: Actions.pop, style: 'cancel'},
                          {text: '好的', onPress: () => {
                            this.handleSwitchStar();
                            Actions.pop()
                          }},
                        ]
                      )
                    }else{
                      Actions.pop()
                    }

                  }
              }}
              right={[{
                  icon: starIcon,
                  iconFamily: "FontAwesome",
                  iconSize: 20,
                  onPress: this.handleSwitchStar
              },{
                  label: arrowLabel,
                  onPress: this.handleSwitchOrder
              }]}
          />
      </Container>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return {
    params : state.get('directory')
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    fetchListFromDB: bindActionCreators(fetchListFromDB, dispatch),
    fetchListFromNetwork: bindActionCreators(fetchListFromNetwork, dispatch),
    updateListOrder: bindActionCreators(updateListOrder, dispatch),
    updateLastRead: bindActionCreators(updateLastRead, dispatch),
    fetchNovels: bindActionCreators(fetch, dispatch),

  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Directory);<commit_msg>优化 star<commit_after>//@flow
import React from 'react';
import {
  View,
  InteractionManager,
  Dimensions,
  Platform,
  Alert,
} from 'react-native';
import {Actions} from 'react-native-router-flux';
import Spinner from 'react-native-spinkit';
import { Container,
 Navbar } from 'navbar-native';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
var MessageBarManager = require('react-native-message-bar').MessageBarManager;

import Item from './Components/Item';
import {fetchListFromDB,fetchListFromNetwork,updateListOrder,updateLastRead} from '../../ducks/directory';
import {fetch} from '../../ducks/bookshelf';

class Directory extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      star:props.novel.star
    };
  }

  componentWillMount() {
    this.props.fetchListFromDB(this.props.novel);

    // MessageBarManager.registerMessageBar(this.refs.alert);
  }
  // componentWillUnmount() {
  //   // Remove the alert located on this master page from the manager
  //   MessageBarManager.unregisterMessageBar();
  // }
  componentDidMount() {
    this.props.fetchListFromNetwork(this.props.novel);

    // MessageBarManager.showAlert({
    //   title: 'Your alert title goes here',
    //   message: 'Your alert message goes here',
    //   alertType: 'success',
    //   // See Properties section for full customization
    //   // Or check `index.ios.js` or `index.android.js` for a complete example
    // });
  }

  handleSwitchStar = ()=>{
    let starResult = !this.state.star;
    this.setState({
      star:starResult
    })
    realmFactory().write(()=>{
      this.props.novel.star = starResult;
      this.props.novel.starAt = new Date();
      //fetch list
      this.props.fetchNovels();
    });
  }

  handleSwitchOrder = ()=>{
    this.props.updateListOrder();
  }

  handleClickArticle = (article:Article,rowIndex:number)=>{
    let index = parseInt(rowIndex);
    if(this.props.params.get('order') == 'desc'){
      index = this.props.params.get('directory').size - index -1;
    }
    InteractionManager.runAfterInteractions(()=>{
      realmFactory().write(()=>{
        this.props.novel.lastReadIndex = index;
        this.props.novel.lastReadTitle = article.get('title');
        this.props.updateLastRead(index);
        this.forceUpdate();
      });
    });

    Actions.reader({
      novel:this.props.novel,
      directory:this.props.params.get('directory'),
      index
    });

  }

  lastScrollIndex = 0;
  scrollTo=(index)=>{
    if(this._scrollView ){
      if(index<0){
        index = 0;
      }
      InteractionManager.runAfterInteractions(() => {
        if(this._scrollView.scrollTo){
          var {height, width} = Dimensions.get('window');
          var rowMargin = height/49/2 - 2;
          if (index>rowMargin) {
            index -= rowMargin;
          }
          this._scrollView.getScrollResponder().scrollResponderScrollTo({y:index*49,animated:false});
        }
      });
      this.lastScrollIndex = index;
    }
  };

  getCurrentScrollIndex=(props = this.props)=>{
    if(props.params.get('order') == 'desc'){
      return props.params.get('directory').size-props.params.get('lastReadIndex')-3;
    }else{
      return props.params.get('lastReadIndex');
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.novel.directoryUrl!=this.props.novel.directoryUrl) {
      this.props.fetchListFromDB(nextProps.novel);
    }else if( nextProps.params.get('lastReadIndex')!=this.props.params.get('lastReadIndex')){
      let index = this.getCurrentScrollIndex(nextProps);
      if(Math.abs(index-this.lastScrollIndex)>=5){
        this.scrollTo(index);
      }
    }
  }

  _scrollView;
  render() {
    let self = this;
    let arrowLabel = '正序';
    let containerParams = {};

    if (this.props.params.get('fetching')) {
      containerParams.loading={
        styleContainer:{
          // marginTop:Platform.OS == 'ios'?64:40,
          backgroundColor:'rgba(102,102,102,.5)'
        },
        coverNavbar:false
      }
      containerParams.data = [];
    }else{

      let directory = this.props.params.get('directory');
      if (this.props.params.get('order') == 'desc') {
        directory = directory.reverse();
        arrowLabel = '逆序';
      }
      containerParams.data=directory.toArray();
    }

    containerParams.row= (rowData,_,rowID)=>{
      return <Item onPress={self.handleClickArticle.bind(null,rowData,rowID)} item={rowData}/>;
    }
    containerParams.type="list";
    containerParams.enableEmptySections=true;
    containerParams.initialListSize=100;
    containerParams.pageSize=200;
    containerParams.onEndReachedThreshold=0;
    containerParams.scrollRenderAheadDistance=1000;
    containerParams.contentRef = (_scrollView)=>{
      this._scrollView=_scrollView
    };

    let starIcon = "star-o";
    if(this.props.novel.star){
      starIcon = "star";
    }
    return (
      <Container
      {...containerParams}
      >
          <Navbar
              title={this.props.novel.title}
              left={{
                  icon: "ios-arrow-back",
                  label: "返回",
                  onPress: ()=>{
                    if (!this.props.novel.star) {
                      Alert.alert(
                        '提醒',
                        '未加入收藏,是否现在加入收藏?',
                        [
                          {text: '不', onPress: Actions.pop, style: 'cancel'},
                          {text: '好的', onPress: () => {
                            this.handleSwitchStar();
                            Actions.pop()
                          }},
                        ]
                      )
                    }else{
                      Actions.pop()
                    }

                  }
              }}
              right={[{
                  icon: starIcon,
                  iconFamily: "FontAwesome",
                  iconSize: 20,
                  onPress: this.handleSwitchStar
              },{
                  label: arrowLabel,
                  onPress: this.handleSwitchOrder
              }]}
          />
      </Container>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  return {
    params : state.get('directory')
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    fetchListFromDB: bindActionCreators(fetchListFromDB, dispatch),
    fetchListFromNetwork: bindActionCreators(fetchListFromNetwork, dispatch),
    updateListOrder: bindActionCreators(updateListOrder, dispatch),
    updateLastRead: bindActionCreators(updateLastRead, dispatch),
    fetchNovels: bindActionCreators(fetch, dispatch),

  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Directory);<|endoftext|>