<commit_before>/**
 * Vow-fs
 *
 * Copyright (c) 2013 Filatov Dmitry (dfilatov@yandex-team.ru)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * @version 0.2.2
 */

var Vow = require('vow'),
    Queue = require('vow-queue'),
    openFilesQueue = new Queue(),
    fs = require('fs'),
    path = require('path'),
    os = require('os'),
    uuid = require('node-uuid'),
    slice = Array.prototype.slice,
    promisify = function(nodeFn) {
        return function() {
            var promise = Vow.promise(),
                args = slice.call(arguments);
            args.push(function(err) {
                err? promise.reject(err) : promise.fulfill(arguments[1]);
            });
            nodeFn.apply(fs, args);
            return promise;
        };
    },
    tmpDir = os.tmpdir || os.tmpDir || function() { return '/tmp'; },
    makeDir = promisify(fs.mkdir),
    removeDir = promisify(fs.rmdir),
    lstat = promisify(fs.lstat),
    emfileTimeout = 1,
    emfileFixWrapper = function(method, weight) {
        var wrapper = function() {
                var callArgs = arguments;
                return openFilesQueue.enqueue(function() {
                    return method.apply(vfs, callArgs).then(
                       function(res) {
                           emfileTimeout = Math.max(1, emfileTimeout / 2);
                           return res;
                       },
                       function(err) {
                           if(err.code === 'EMFILE') {
                               emfileTimeout++;
                               return Vow.delay(null, emfileTimeout).then(function() {
                                   return wrapper.apply(vfs, callArgs);
                               });
                           }
                           else {
                               throw err;
                           }
                       });
                }, weight);
           };
           return wrapper;
    },
    undef;

var vfs = module.exports = {
    /**
     * Read file by given path
     * @param {String} path
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    read : emfileFixWrapper(promisify(fs.readFile)),

    /**
     * Write data to file by given path
     * @param {String} path
     * @param {String|Buffer} data
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    write : emfileFixWrapper(promisify(fs.writeFile)),

    /**
     * Append data to file by given path
     * @param {String} path
     * @param {String|Buffer} data
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    append : emfileFixWrapper(promisify(fs.appendFile)),

    /**
     * Remove file at given path
     * @param {String} pathToRemove
     * @returns {Vow.promise}
     */
    remove : promisify(fs.unlink),

    /**
     * Copy file from sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    copy : emfileFixWrapper(function(sourcePath, targetPath) {
        return this.isFile(sourcePath).then(function(isFile) {
            if(!isFile) {
                var err = Error();
                err.errno = 28;
                err.code = 'EISDIR';
                err.path = sourcePath;
                throw err;
            }

            var promise = Vow.promise(),
                sourceStream = fs.createReadStream(sourcePath),
                errFn = function(err) {
                    promise.reject(err);
                };

            sourceStream
                .on('error', errFn)
                .on('open', function() {
                    var targetStream = fs.createWriteStream(targetPath);
                    sourceStream.pipe(
                        targetStream
                            .on('error', errFn)
                            .on('close', function() {
                                promise.fulfill();
                            }));
                });

            return promise;
        });
    }, 2),

    /**
     * Move from sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    move : promisify(fs.rename),

    /**
     * Extract fs.Stats about a given path
     * @param {String} path
     * @returns {Vow.promise}
     */
    stat : promisify(fs.stat),

    /**
     * Test whether or not the given path exists
     * @param {String} path
     * @returns {Vow.promise}
     */
    exists : fs.exists?
        function(path) {
            var promise = Vow.promise();
            fs.exists(path, function(exists) {
                promise.fulfill(exists);
            });
            return promise;
        } :
        function(path) {
            var promise = Vow.promise();
            fs.stat(path, function(err) {
                promise.fulfill(!err);
            });
            return promise;
        },

    /**
     * Create a hard link from the sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    link : promisify(fs.link),

    /**
     * Create a relative symbolic link from the sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @param {String} [type=file] can be either 'dir', 'file', or 'junction'
     * @returns {Vow.promise}
     */
    symLink : promisify(fs.symlink),

    /**
     * Change the owner for a given path using Unix user-id and group-id numbers
     * @param {String} path
     * @param uid
     * @param gid
     * @returns {Vow.promise}
     */
    chown : promisify(fs.chown),

    /**
     * Change the Unix mode for a path. Returns a promise
     * @param {String} path
     * @param mode
     * @returns {Vow.promise}
     */
    chmod : promisify(fs.chmod),

    /**
     * Normalizes a given path to absolute path
     * @param {String} path
     * @returns {Vow.promise}
     */
    absolute : promisify(fs.realpath),

    /**
     * Check whether the given path is a file
     * @param {String} path
     * @returns {Vow.promise}
     */
    isFile : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isFile();
        });
    },

    /**
     * Check whether the given path is a directory
     * @param {String} path
     * @returns {Vow.promise}
     */
    isDir : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isDirectory();
        });
    },

    /**
     * Check whether the given path is a socket
     * @param {String} path
     * @returns {Vow.promise}
     */
    isSocket : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isSocket();
        });
    },

    /**
     * Check whether the given path is a symbolic link
     * @param {String} path
     * @returns {Vow.promise}
     */
    isSymLink : function(path) {
        return lstat(path).then(function(stats) {
            return stats.isSymbolicLink();
        });
    },

    /**
     * Make a temporary file
     * @param {Object} options
     * @param {String} [options.prefix]
     * @param {String} [options.dir=os.tmpdir()]
     * @param {String} [options.ext=tmp]
     * @returns {Vow.promise}
     */
    makeTmpFile : function(options) {
        options || (options = {});

        var filePath = path.join(
                options.dir || tmpDir(),
                (options.prefix || '') + uuid.v4() + (options.ext || '.tmp'));

        return vfs.write(filePath, '').then(function() {
            return filePath;
        });
    },

    /**
     * Read the contents of a directory by given path
     * @param {String} path
     * @returns {Vow.promise}
     */
    listDir : promisify(fs.readdir),

    /**
     * Make a directory at a given path, recursively creating any branches that doesn't exist
     * @param {String} dirPath
     * @param [mode=0777]
     * @param [failIfExist=false]
     * @returns {Vow.promise}
     */
    makeDir : function(dirPath, mode, failIfExist) {
        if(typeof mode === 'boolean') {
            failIfExist = mode;
            mode = undef;
        }

        var dirName = path.dirname(dirPath),
            onFailed = function(e) {
                if(e.code !== 'EEXIST' || failIfExist) {
                    throw e;
                }

                return vfs.isDir(dirPath).then(function(isDir) {
                    if(!isDir) {
                        throw e;
                    }
                });
            };

        return vfs.exists(dirName).then(function(exists) {
            if(exists) {
                return makeDir(dirPath, mode).fail(onFailed);
            }
            else {
                failIfExist = false;
                return vfs.makeDir(dirName, mode).then(function() {
                    return makeDir(dirPath, mode).fail(onFailed);
                });
            }
        });
    },

    /**
     * Remove directory
     * @param {String} dirPath
     * @returns {Vow.promise}
     */
    removeDir : function(dirPath) {
        return vfs.listDir(dirPath)
            .then(function(list) {
                return list.length && Vow.all(
                    list.map(function(file) {
                        var fullPath = path.join(dirPath, file);
                        return vfs.isFile(fullPath).then(function(isFile) {
                            return isFile?
                                vfs.remove(fullPath) :
                                vfs.removeDir(fullPath);
                        });
                    }));
            })
            .then(function() {
                return removeDir(dirPath);
            });
    },

    options : function(opts) {
        if(typeof opts.openFileLimit !== 'undefined') {
            openFilesQueue.params({ weightLimit : opts.openFileLimit });
        }
    }
};
<commit_msg>EMFILE handling for readdir (#9)<commit_after>/**
 * Vow-fs
 *
 * Copyright (c) 2013 Filatov Dmitry (dfilatov@yandex-team.ru)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * @version 0.2.2
 */

var Vow = require('vow'),
    Queue = require('vow-queue'),
    openFilesQueue = new Queue(),
    fs = require('fs'),
    path = require('path'),
    os = require('os'),
    uuid = require('node-uuid'),
    slice = Array.prototype.slice,
    promisify = function(nodeFn) {
        return function() {
            var promise = Vow.promise(),
                args = slice.call(arguments);
            args.push(function(err) {
                err? promise.reject(err) : promise.fulfill(arguments[1]);
            });
            nodeFn.apply(fs, args);
            return promise;
        };
    },
    tmpDir = os.tmpdir || os.tmpDir || function() { return '/tmp'; },
    makeDir = promisify(fs.mkdir),
    removeDir = promisify(fs.rmdir),
    lstat = promisify(fs.lstat),
    emfileTimeout = 1,
    emfileFixWrapper = function(method, weight) {
        var wrapper = function() {
                var callArgs = arguments;
                return openFilesQueue.enqueue(function() {
                    return method.apply(vfs, callArgs).then(
                       function(res) {
                           emfileTimeout = Math.max(1, emfileTimeout / 2);
                           return res;
                       },
                       function(err) {
                           if(err.code === 'EMFILE') {
                               emfileTimeout++;
                               return Vow.delay(null, emfileTimeout).then(function() {
                                   return wrapper.apply(vfs, callArgs);
                               });
                           }
                           else {
                               throw err;
                           }
                       });
                }, weight);
           };
           return wrapper;
    },
    undef;

var vfs = module.exports = {
    /**
     * Read file by given path
     * @param {String} path
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    read : emfileFixWrapper(promisify(fs.readFile)),

    /**
     * Write data to file by given path
     * @param {String} path
     * @param {String|Buffer} data
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    write : emfileFixWrapper(promisify(fs.writeFile)),

    /**
     * Append data to file by given path
     * @param {String} path
     * @param {String|Buffer} data
     * @param {String} [encoding=utf8]
     * @returns {Vow.promise}
     */
    append : emfileFixWrapper(promisify(fs.appendFile)),

    /**
     * Remove file at given path
     * @param {String} pathToRemove
     * @returns {Vow.promise}
     */
    remove : promisify(fs.unlink),

    /**
     * Copy file from sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    copy : emfileFixWrapper(function(sourcePath, targetPath) {
        return this.isFile(sourcePath).then(function(isFile) {
            if(!isFile) {
                var err = Error();
                err.errno = 28;
                err.code = 'EISDIR';
                err.path = sourcePath;
                throw err;
            }

            var promise = Vow.promise(),
                sourceStream = fs.createReadStream(sourcePath),
                errFn = function(err) {
                    promise.reject(err);
                };

            sourceStream
                .on('error', errFn)
                .on('open', function() {
                    var targetStream = fs.createWriteStream(targetPath);
                    sourceStream.pipe(
                        targetStream
                            .on('error', errFn)
                            .on('close', function() {
                                promise.fulfill();
                            }));
                });

            return promise;
        });
    }, 2),

    /**
     * Move from sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    move : promisify(fs.rename),

    /**
     * Extract fs.Stats about a given path
     * @param {String} path
     * @returns {Vow.promise}
     */
    stat : promisify(fs.stat),

    /**
     * Test whether or not the given path exists
     * @param {String} path
     * @returns {Vow.promise}
     */
    exists : fs.exists?
        function(path) {
            var promise = Vow.promise();
            fs.exists(path, function(exists) {
                promise.fulfill(exists);
            });
            return promise;
        } :
        function(path) {
            var promise = Vow.promise();
            fs.stat(path, function(err) {
                promise.fulfill(!err);
            });
            return promise;
        },

    /**
     * Create a hard link from the sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @returns {Vow.promise}
     */
    link : promisify(fs.link),

    /**
     * Create a relative symbolic link from the sourcePath to targetPath
     * @param {String} sourcePath
     * @param {String} targetPath
     * @param {String} [type=file] can be either 'dir', 'file', or 'junction'
     * @returns {Vow.promise}
     */
    symLink : promisify(fs.symlink),

    /**
     * Change the owner for a given path using Unix user-id and group-id numbers
     * @param {String} path
     * @param uid
     * @param gid
     * @returns {Vow.promise}
     */
    chown : promisify(fs.chown),

    /**
     * Change the Unix mode for a path. Returns a promise
     * @param {String} path
     * @param mode
     * @returns {Vow.promise}
     */
    chmod : promisify(fs.chmod),

    /**
     * Normalizes a given path to absolute path
     * @param {String} path
     * @returns {Vow.promise}
     */
    absolute : promisify(fs.realpath),

    /**
     * Check whether the given path is a file
     * @param {String} path
     * @returns {Vow.promise}
     */
    isFile : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isFile();
        });
    },

    /**
     * Check whether the given path is a directory
     * @param {String} path
     * @returns {Vow.promise}
     */
    isDir : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isDirectory();
        });
    },

    /**
     * Check whether the given path is a socket
     * @param {String} path
     * @returns {Vow.promise}
     */
    isSocket : function(path) {
        return this.stat(path).then(function(stats) {
            return stats.isSocket();
        });
    },

    /**
     * Check whether the given path is a symbolic link
     * @param {String} path
     * @returns {Vow.promise}
     */
    isSymLink : function(path) {
        return lstat(path).then(function(stats) {
            return stats.isSymbolicLink();
        });
    },

    /**
     * Make a temporary file
     * @param {Object} options
     * @param {String} [options.prefix]
     * @param {String} [options.dir=os.tmpdir()]
     * @param {String} [options.ext=tmp]
     * @returns {Vow.promise}
     */
    makeTmpFile : function(options) {
        options || (options = {});

        var filePath = path.join(
                options.dir || tmpDir(),
                (options.prefix || '') + uuid.v4() + (options.ext || '.tmp'));

        return vfs.write(filePath, '').then(function() {
            return filePath;
        });
    },

    /**
     * Read the contents of a directory by given path
     * @param {String} path
     * @returns {Vow.promise}
     */
    listDir : emfileFixWrapper(promisify(fs.readdir)),

    /**
     * Make a directory at a given path, recursively creating any branches that doesn't exist
     * @param {String} dirPath
     * @param [mode=0777]
     * @param [failIfExist=false]
     * @returns {Vow.promise}
     */
    makeDir : function(dirPath, mode, failIfExist) {
        if(typeof mode === 'boolean') {
            failIfExist = mode;
            mode = undef;
        }

        var dirName = path.dirname(dirPath),
            onFailed = function(e) {
                if(e.code !== 'EEXIST' || failIfExist) {
                    throw e;
                }

                return vfs.isDir(dirPath).then(function(isDir) {
                    if(!isDir) {
                        throw e;
                    }
                });
            };

        return vfs.exists(dirName).then(function(exists) {
            if(exists) {
                return makeDir(dirPath, mode).fail(onFailed);
            }
            else {
                failIfExist = false;
                return vfs.makeDir(dirName, mode).then(function() {
                    return makeDir(dirPath, mode).fail(onFailed);
                });
            }
        });
    },

    /**
     * Remove directory
     * @param {String} dirPath
     * @returns {Vow.promise}
     */
    removeDir : function(dirPath) {
        return vfs.listDir(dirPath)
            .then(function(list) {
                return list.length && Vow.all(
                    list.map(function(file) {
                        var fullPath = path.join(dirPath, file);
                        return vfs.isFile(fullPath).then(function(isFile) {
                            return isFile?
                                vfs.remove(fullPath) :
                                vfs.removeDir(fullPath);
                        });
                    }));
            })
            .then(function() {
                return removeDir(dirPath);
            });
    },

    options : function(opts) {
        if(typeof opts.openFileLimit !== 'undefined') {
            openFilesQueue.params({ weightLimit : opts.openFileLimit });
        }
    }
};
<|endoftext|>


<commit_before>import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize: function(serialized) {
    var map = {
      0: 'New',
      20: 'Started',
      25: 'Reviewed',
      30: 'Finished',
    };
    return map[serialized];
  },

  serialize: function(deserialized) {
    var map = {
      'New': 0,
      'Started': 20,
      'Reviewed': 25,
      'Finished': 30,
};
    return map[deserialized];
  }
});
<commit_msg>Add `Built` to round status<commit_after>import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize: function(serialized) {
    var map = {
      0: 'New',
      10: 'Built',
      20: 'Started',
      25: 'Reviewed',
      30: 'Finished',
    };
    return map[serialized];
  },

  serialize: function(deserialized) {
    var map = {
      'New': 0,
      'Built': 10,
      'Started': 20,
      'Reviewed': 25,
      'Finished': 30,
};
    return map[deserialized];
  }
});
<|endoftext|>


<commit_before>var git = require('nodegit');
var exec = require('child_process').exec;
var chalk = require('chalk');

// Output styling.
var success = chalk.green;
var notice = chalk.yellow;
var whoops = chalk.bold.red; // Can't name error as exec uses error in callback.
var underline = chalk.underline;

exports.getCurrentRepo = function() {
	return git.Repository.open("./");
};

exports.init = function() {
	exec('git init', function(error, stdout, stderr) {
		if (stdout.substring(0, 13) == 'Reinitialized') {
			console.log(notice('[~] Reinitialized existing Git repository.'));
		} else {
			console.log(success('[✔] Initialized existing Git repository.'));
		}
	});
};

exports.addAll = function() {
	exec('git add -A');

	console.log(success('[✔] Added everything!'));
};

exports.commit = function(message) {
	// No commit message.
	if (message === '') {
		console.log(notice('[~] You must enter a commit message.'));
	} else {
		this.addAll();
		exec('git commit -m "' + message + '"');

		console.log(success('[✔] Commited!'));
		console.log('\n"' + underline(message) + '"');
	}
};

exports.push = function() {
	exec('git push', function(error, stdout, stderr) {
		if (stderr.substring(0, 10) == 'Everything') {
			console.log(notice('[~] Everything already pushed.'));
		} else if (stderr.substring(0, 2) == 'To') {
			console.log(success('[✔] Pushed!'));
		} else {
			console.log(whoops('[✖] Could not push commits.'));
		}
	});
};

exports.status = function() {

};

// https://gist.github.com/textarcana/1306223
exports.log = function() {
	exec('git log --pretty=format:\'{%n  "commit": "%H",%n  "author": "%an <%ae>",%n  "date": "%ad",%n  "message": "%f"%n},\' $@ | perl -pe \'BEGIN{print "["}; END{print "]\n"}\' | perl -pe \'s/},]/}]/\'', function(error, stdout, stderr) {
		var log = JSON.parse(stdout);
		log.reverse(); // Show newest at the bottom.

		for (var i = 0; i < log.length; i++) {
			console.log(); // New line between each commit.

			console.log(chalk.yellow('[' + log[i].commit + ']'));

			var author = {
				name: log[i].author.split('<')[0].trim(),
				email: '<' + log[i].author.split('<')[1]
			}

			console.log('|- ' + chalk.gray(author.name) + " " + chalk.gray.dim(author.email));
			console.log('|- ' + chalk.gray.dim(log[i].date));
			console.log('|- ' + chalk.green(log[i].message.split('-').join(' ')));
		}
	});
};
<commit_msg>Working on error handling of commit shortcut.<commit_after>var git = require('nodegit');
var exec = require('child_process').exec;
var chalk = require('chalk');

// Output styling.
var success = chalk.green;
var notice = chalk.yellow;
var whoops = chalk.bold.red; // Can't name error as exec uses error in callback.
var underline = chalk.underline;

exports.getCurrentRepo = function() {
	return git.Repository.open("./");
};

exports.init = function() {
	exec('git init', function(error, stdout, stderr) {
		if (stdout.substring(0, 13) == 'Reinitialized') {
			console.log(notice('[~] Reinitialized existing Git repository.'));
		} else {
			console.log(success('[✔] Initialized existing Git repository.'));
		}
	});
};

exports.addAll = function() {
	exec('git add -A');

	console.log(success('[✔] Added everything!'));
};

exports.commit = function(message) {
	// No commit message.
	if (message === '') {
		console.log(notice('[~] You must enter a commit message.'));
	} else {
		this.addAll();
		exec('git commit -m "' + message + '"', function(error, stdout, stderr) {
			console.log(success('[✔] Commited!'));
			console.log('\n"' + underline(message) + '"');
		});
	}
};

exports.push = function() {
	exec('git push', function(error, stdout, stderr) {
		if (stderr.substring(0, 10) == 'Everything') {
			console.log(notice('[~] Everything already pushed.'));
		} else if (stderr.substring(0, 2) == 'To') {
			console.log(success('[✔] Pushed!'));
		} else {
			console.log(whoops('[✖] Could not push commits.'));
		}
	});
};

exports.status = function() {

};

// https://gist.github.com/textarcana/1306223
exports.log = function() {
	exec('git log --pretty=format:\'{%n  "commit": "%H",%n  "author": "%an <%ae>",%n  "date": "%ad",%n  "message": "%f"%n},\' $@ | perl -pe \'BEGIN{print "["}; END{print "]\n"}\' | perl -pe \'s/},]/}]/\'', function(error, stdout, stderr) {
		var log = JSON.parse(stdout);
		log.reverse(); // Show newest at the bottom.

		for (var i = 0; i < log.length; i++) {
			console.log(); // New line between each commit.

			console.log(chalk.yellow('[' + log[i].commit + ']'));

			var author = {
				name: log[i].author.split('<')[0].trim(),
				email: '<' + log[i].author.split('<')[1]
			}

			console.log('|- ' + chalk.gray(author.name) + " " + chalk.gray.dim(author.email));
			console.log('|- ' + chalk.gray.dim(log[i].date));
			console.log('|- ' + chalk.green(log[i].message.split('-').join(' ')));
		}
	});
};
<|endoftext|>


<commit_before>$torrentInput = $('.menu input[name="torrent-link"]')
$startTorrentBut = $('.menu input[name="torrent-start"]')
$searchTorrentBut = $('.menu input[name="torrent-search"]')
$currentSubmit = $searchTorrentBut
$searchResultList = $('.menu .search-result')

$torrentInput.keyup(function () {
  var value = $(this).val()
  if (value.search('.torrent') != -1) {
    $startTorrentBut.show()
    $searchTorrentBut.hide()
    $currentSubmit = $startTorrentBut
  } else {
    $startTorrentBut.hide()
    $searchTorrentBut.show()
    $currentSubmit = $searchTorrentBut
  }

})

$startTorrentBut.click(function () {
  if ($torrentInput.val()) {
    socket.emit('download-t', $torrentInput.val())
    $torrentInput.val('')
  }
})

$searchTorrentBut.click(function () {
  if ($torrentInput.val()) {
    socket.emit('search-t', $torrentInput.val())
    $torrentInput.val('')
    $searchResultList.html('')
  }
})

$('.search-result').on('click', 'li', function () {
  $searchResultList.html('')
  $torrentInput.val($(this).attr('torrent-link'))
  $torrentInput.trigger('keyup')
})

function appendTorrent (torrent) {
  if ($('.torrent[hash=' + torrent.hash + ']').length > 0) {
    var $torrent = $('.torrent[hash=' + torrent.hash + ']')
    $torrent.html('')
    var needToAppend = 0
  } else {
    var $torrent = $('<tr>').addClass('torrent').attr('hash', torrent.hash)
    var needToAppend = 1
  }

  if (torrent.alter === 1) {
    $torrent.addClass('alter')
  }

  var $name = $('<td>').addClass('name').text(formatName(torrent.name.substring(0, 50))).appendTo($torrent)
  var $size = $('<td>').addClass('size').text(formatSize(torrent.size)).appendTo($torrent)
  var $progress = $('<td>').addClass('progress').append(
    $('<progress>').attr('max', 1).attr('value', torrent.progress),
    $('<p>').addClass('percent').text(Math.round(torrent.progress * 100) + '%'),
    $('<p>').addClass('remaining-time').text(formatTime(torrent.timeRemaining))
  ).appendTo($torrent)
  var $downspeed = $('<td>').addClass('sdown').text(formatSpeed(torrent.sdown) + ' (' + torrent.seed + ')').appendTo($torrent)
  var $upspeed = $('<td>').addClass('sup').text(formatSpeed(torrent.sup)).appendTo($torrent)

  var $actions = $('<td>').addClass('actions')

  var $deleteBut = $('<i>').addClass('but fa fa-remove').attr('id', 'delete').text('delete').appendTo($actions).click(function () {
    if (confirm('Confirmer la suppression ?')) {
      socket.emit('remove-t', $(this).parent().parent().attr('hash'))
    }
  })
  $actions.appendTo($torrent)

  if (needToAppend) {
    $torrent.appendTo('.container .torrent .list')
  }
}
<commit_msg>trigger key up on start download<commit_after>$torrentInput = $('.menu input[name="torrent-link"]')
$startTorrentBut = $('.menu input[name="torrent-start"]')
$searchTorrentBut = $('.menu input[name="torrent-search"]')
$currentSubmit = $searchTorrentBut
$searchResultList = $('.menu .search-result')

$torrentInput.keyup(function () {
  var value = $(this).val()
  if (value.search('.torrent') != -1) {
    $startTorrentBut.show()
    $searchTorrentBut.hide()
    $currentSubmit = $startTorrentBut
  } else {
    $startTorrentBut.hide()
    $searchTorrentBut.show()
    $currentSubmit = $searchTorrentBut
  }

})

$startTorrentBut.click(function () {
  if ($torrentInput.val()) {
    socket.emit('download-t', $torrentInput.val())
    $torrentInput.val('')
    $torrentInput.trigger('keyup')
  }
})

$searchTorrentBut.click(function () {
  if ($torrentInput.val()) {
    socket.emit('search-t', $torrentInput.val())
    $torrentInput.val('')
    $searchResultList.html('')
  }
})

$('.search-result').on('click', 'li', function () {
  $searchResultList.html('')
  $torrentInput.val($(this).attr('torrent-link'))
  $torrentInput.trigger('keyup')
})

function appendTorrent (torrent) {
  if ($('.torrent[hash=' + torrent.hash + ']').length > 0) {
    var $torrent = $('.torrent[hash=' + torrent.hash + ']')
    $torrent.html('')
    var needToAppend = 0
  } else {
    var $torrent = $('<tr>').addClass('torrent').attr('hash', torrent.hash)
    var needToAppend = 1
  }

  if (torrent.alter === 1) {
    $torrent.addClass('alter')
  }

  var $name = $('<td>').addClass('name').text(formatName(torrent.name.substring(0, 50))).appendTo($torrent)
  var $size = $('<td>').addClass('size').text(formatSize(torrent.size)).appendTo($torrent)
  var $progress = $('<td>').addClass('progress').append(
    $('<progress>').attr('max', 1).attr('value', torrent.progress),
    $('<p>').addClass('percent').text(Math.round(torrent.progress * 100) + '%'),
    $('<p>').addClass('remaining-time').text(formatTime(torrent.timeRemaining))
  ).appendTo($torrent)
  var $downspeed = $('<td>').addClass('sdown').text(formatSpeed(torrent.sdown) + ' (' + torrent.seed + ')').appendTo($torrent)
  var $upspeed = $('<td>').addClass('sup').text(formatSpeed(torrent.sup)).appendTo($torrent)

  var $actions = $('<td>').addClass('actions')

  var $deleteBut = $('<i>').addClass('but fa fa-remove').attr('id', 'delete').text('delete').appendTo($actions).click(function () {
    if (confirm('Confirmer la suppression ?')) {
      socket.emit('remove-t', $(this).parent().parent().attr('hash'))
    }
  })
  $actions.appendTo($torrent)

  if (needToAppend) {
    $torrent.appendTo('.container .torrent .list')
  }
}
<|endoftext|>


<commit_before>"use strict";

const socket = require("../socket");
const wrapCursor = require("undate").wrapCursor;

socket.on("upload:success", (url) => {
	const fullURL = new URL(url, location);
	const textbox = document.getElementById("input");
	wrapCursor(textbox, fullURL, " ");
});
<commit_msg>Fix up link insertion after uploads to be saner<commit_after>"use strict";

const socket = require("../socket");
const updateCursor = require("undate").update;

socket.on("upload:success", (url) => {
	const fullURL = (new URL(url, location)).toString();
	const textbox = document.getElementById("input");
	const initStart = textbox.selectionStart;

	// Get the text before the cursor, and add a space if it's not in the beginning
	const headToCursor = initStart > 0 ? (textbox.value.substr(0, initStart) + " ") : "";

	// Get the remaining text after the cursor
	const cursorToTail = textbox.value.substr(initStart);

	// Construct the value until the point where we want the cursor to be
	const textBeforeTail = headToCursor + fullURL + " ";

	updateCursor(textbox, textBeforeTail + cursorToTail);

	// Set the cursor after the link and a space
	textbox.selectionStart = textbox.selectionEnd = textBeforeTail.length;
});
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import utils from 'utils'
import deepEqual from 'deep-equal'
import autobind from 'autobind-decorator'
import {FormGroup, Col, ControlLabel, FormControl, InputGroup, HelpBlock} from 'react-bootstrap'

class FormFieldExtraCol extends Component {
	render() {
		return <Col sm={3} {...this.props} />
	}
}

export default class FormField extends Component {
	constructor(props, context) {
		super(props, context)
		this.state = {
			value: '',
			userHasTouchedField: false,
			isValid: null
		}
	}
	static contextTypes = {
		formFor: PropTypes.object,
		form: PropTypes.object,
	}

	static propTypes = {
		// Specifying an id prop on a FormField contained inside a Form with
		// a formFor prop will cause the FormField to be autobound to the formFor
		// value. That is to say, its value will be set to formForObject[idProp],
		// and when the FormField changes, formForObject[idProp] will automatically
		// be updated. The form will then have its own onChange fired to allow
		// you to update state or rerender.
		id: PropTypes.string.isRequired,
		label: PropTypes.string,

		// if you need to do additional formatting on the value returned by
		// formForObject[idProp], you can specify a getter function which
		// will be called with the value as its prop
		getter: PropTypes.func,

		// This will cause the FormField to be rendered as an InputGroup,
		// with the node specified by addon appended on the right of the group.
		addon: PropTypes.node,

		// If you pass children, we will try to autobind them to the id key
		// if any of the children have propTypes that include onChange
		children: PropTypes.node,

		humanName: PropTypes.string,
		required: PropTypes.bool,
		onError: PropTypes.func,
		onValid: PropTypes.func,

		// If you don't pass children, we will automatically create a FormControl.
		// You can use componentClass to override its type (for example, for a select).
		componentClass: PropTypes.oneOfType([
			PropTypes.string,
			PropTypes.object,
			PropTypes.func,
		]),

		// If you don't want autobinding behavior, you can override them here
		value: PropTypes.oneOfType([
			PropTypes.string,
			PropTypes.object,
			PropTypes.array,
			PropTypes.bool,
		]),

		onChange: PropTypes.func,

		maxCharacters: PropTypes.number,
	}

	render() {
		let {
			id,
			className,
			label,
			icon,
			addon,
			children,
			postInputGroupChildren,
			canSubmitWithError,
			...childProps
		} = this.props

		childProps = Object.without(
			childProps,
			'getter', 'horizontal', 'onError', 'onValid', 'humanName', 'maxCharacters', 'validateBeforeUserTouches'
		)
		if (canSubmitWithError) {
			childProps = Object.without(childProps, 'required')
		}

		let defaultValue = this.getDefaultValue(this.props, this.context)

		let state = this.state
		if (Array.isArray(defaultValue)) {
			state.value = Array.from(defaultValue)
		} else {
			state.value = defaultValue
		}

		const validationState = this.props.validationState ||
			(this.state.isValid === false || this.isMissingRequiredField(this.props)) ?
				(canSubmitWithError ? 'warning' : 'error')
				: null

		let horizontal = this.context.form && this.context.form.props.horizontal
		if (typeof this.props.horizontal !== 'undefined') {
			horizontal = this.props.horizontal
		}

		if (typeof label === 'undefined') {
			label = utils.sentenceCase(id)
		}

		// Remove an ExtraCol from children first so we can manually append it
		// as a column
		children = React.Children.toArray(children)
		let extra = children.find(child => child.type === FormFieldExtraCol)
		if (extra)
			children.splice(children.indexOf(extra), 1)

		// if type is static, render out a static value
		if (this.props.type === 'static' || (!this.props.type && !this.props.componentClass && this.context.form.props.static)) {
			children = <FormControl.Static componentClass={'div'} id={id} {...childProps}>{(children.length && children) || defaultValue}</FormControl.Static>

		// if children are provided, render those, but special case them to
		// automatically set value and children props
		} else if (!this.props.componentClass && children.length) {
			children = children.map(child => {
				let propTypes = child.type.propTypes

				// check to see if this is some kind of element where we
				// can register an onChange handler, otherwise skip it
				if (propTypes && !propTypes.onChange)
					return child

				return React.cloneElement(child, {value: defaultValue, onChange: child.props.onChange || this.onChange})
			})

		// otherwise render out a default FormControl input element
		} else {
			if (children.length)
				childProps.children = children

			const formControl = <FormControl
				{...childProps}
				value={defaultValue}
				onChange={this.onChange}
				onBlur={this.onUserTouchedField} />

			children =

				{formControl}
				<HelpBlock className={validationState === 'error' || validationState === 'warning' ? '' : 'hidden'} >
					{this.props.humanName} is required
				</HelpBlock>

		}

		if (icon) {
			icon =
		}

		// if there's an addon we need to use an InputGroup
		if (addon) {
			// allows passing a url for an image
			if (addon.indexOf('.') !== -1) {
				addon =
			}

			children =

				<InputGroup>
					{children}
					<InputGroup.Addon onClick={this.focus}>{addon}</InputGroup.Addon>
				</InputGroup>
				{postInputGroupChildren}

		}

		return (
			<FormGroup controlId={id} className={className} validationState={validationState}>
				{horizontal
					? <Col sm={2} componentClass={ControlLabel}>{label} {icon}</Col>
					: <ControlLabel>{label} {icon}</ControlLabel> }
				{horizontal
					? <Col sm={7}>{children}</Col>
					: children }
				{extra}
			</FormGroup>
		)
	}

	@autobind
	isMissingRequiredField(props) {
		return props.required && !this.state.value && this.state.userHasTouchedField
	}

	shouldComponentUpdate(newProps, newState, newContext) {
		if (this.state.userHasTouchedField !== newState.userHasTouchedField) {
			return true
		}

		let newValue = this.getDefaultValue(newProps, newContext)
		let oldValue = this.state.value

		if (newValue !== oldValue) {
			return true
		}

		if (Array.isArray(newValue)) {
			return !deepEqual(newValue, oldValue)
		}

		if (!deepEqual(this.props, newProps)) {
			return true
		}

		return false
	}

	getValue(props, context) {
		let formContext = context.formFor
		let id = props.id
		let getter = props.getter
		if (formContext) {
			let value = formContext[id]
			return getter ? getter(value) : value
		}
	}

	getDefaultValue(props, context) {
		return props.value || this.getValue(props, context) || ''
	}

	componentWillMount() {
		if (this.props.validateBeforeUserTouches) {
			this.setState({userHasTouchedField: true})
		}
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.validateBeforeUserTouches) {
			this.setState({userHasTouchedField: true})
		}

		if (nextProps.required !== this.props.required) {
			this.updateValidationState(nextProps)
		}
	}

	@autobind
	updateValidationState(props) {
		if (!this.state.userHasTouchedField) {
			return
		}

		this.setState({isValid: !this.isMissingRequiredField(props)})

		if (this.isMissingRequiredField(props) || this.state.isValid === false) {
			props.onError()
		} else if (props.onValid && !this.isMissingRequiredField(props) && this.state.isValid !== false) {
			props.onValid()
		}
	}

	@autobind
	onUserTouchedField(event) {
		this.setState({
			isValid: event && event.target ? event.target.checkValidity() : null,
			userHasTouchedField: true
		}, () => this.updateValidationState(this.props))
	}

	@autobind
	onChange(event) {
		if (this.props.onError || this.props.onValid || this.props.required) {
			this.onUserTouchedField(event)
		}

		if (this.props.onChange) {
			this.props.onChange(event)
			return
		}

		let id = this.props.id
		let value = event && event.target ? event.target.value : event

		if (this.props.maxCharacters && value.length > this.props.maxCharacters) {
			return
		}

		let formContext = this.context.formFor
		if (formContext)
			formContext[id] = value

		let form = this.context.form
		if (form && form.props.onChange) {
			form.props.onChange(event)
			event && event.stopPropagation && event.stopPropagation()
		}
	}

	@autobind
	focus() {
		let element = document.getElementById(this.props.id)
		if (element && element.focus) {
			element.focus()
		}
	}
}

FormField.ExtraCol = FormFieldExtraCol
<commit_msg>Listen to change and input events in FormField. Fixes #694<commit_after>import React, {Component, PropTypes} from 'react'
import utils from 'utils'
import deepEqual from 'deep-equal'
import autobind from 'autobind-decorator'
import {FormGroup, Col, ControlLabel, FormControl, InputGroup, HelpBlock} from 'react-bootstrap'

class FormFieldExtraCol extends Component {
	render() {
		return <Col sm={3} {...this.props} />
	}
}

export default class FormField extends Component {
	constructor(props, context) {
		super(props, context)
		this.state = {
			value: '',
			userHasTouchedField: false,
			isValid: null
		}
	}
	static contextTypes = {
		formFor: PropTypes.object,
		form: PropTypes.object,
	}

	static propTypes = {
		// Specifying an id prop on a FormField contained inside a Form with
		// a formFor prop will cause the FormField to be autobound to the formFor
		// value. That is to say, its value will be set to formForObject[idProp],
		// and when the FormField changes, formForObject[idProp] will automatically
		// be updated. The form will then have its own onChange fired to allow
		// you to update state or rerender.
		id: PropTypes.string.isRequired,
		label: PropTypes.string,

		// if you need to do additional formatting on the value returned by
		// formForObject[idProp], you can specify a getter function which
		// will be called with the value as its prop
		getter: PropTypes.func,

		// This will cause the FormField to be rendered as an InputGroup,
		// with the node specified by addon appended on the right of the group.
		addon: PropTypes.node,

		// If you pass children, we will try to autobind them to the id key
		// if any of the children have propTypes that include onChange
		children: PropTypes.node,

		humanName: PropTypes.string,
		required: PropTypes.bool,
		onError: PropTypes.func,
		onValid: PropTypes.func,

		// If you don't pass children, we will automatically create a FormControl.
		// You can use componentClass to override its type (for example, for a select).
		componentClass: PropTypes.oneOfType([
			PropTypes.string,
			PropTypes.object,
			PropTypes.func,
		]),

		// If you don't want autobinding behavior, you can override them here
		value: PropTypes.oneOfType([
			PropTypes.string,
			PropTypes.object,
			PropTypes.array,
			PropTypes.bool,
		]),

		onChange: PropTypes.func,

		maxCharacters: PropTypes.number,
	}

	render() {
		let {
			id,
			className,
			label,
			icon,
			addon,
			children,
			postInputGroupChildren,
			canSubmitWithError,
			...childProps
		} = this.props

		childProps = Object.without(
			childProps,
			'getter', 'horizontal', 'onError', 'onValid', 'humanName', 'maxCharacters', 'validateBeforeUserTouches'
		)
		if (canSubmitWithError) {
			childProps = Object.without(childProps, 'required')
		}

		let defaultValue = this.getDefaultValue(this.props, this.context)

		let state = this.state
		if (Array.isArray(defaultValue)) {
			state.value = Array.from(defaultValue)
		} else {
			state.value = defaultValue
		}

		const validationState = this.props.validationState ||
			(this.state.isValid === false || this.isMissingRequiredField(this.props)) ?
				(canSubmitWithError ? 'warning' : 'error')
				: null

		let horizontal = this.context.form && this.context.form.props.horizontal
		if (typeof this.props.horizontal !== 'undefined') {
			horizontal = this.props.horizontal
		}

		if (typeof label === 'undefined') {
			label = utils.sentenceCase(id)
		}

		// Remove an ExtraCol from children first so we can manually append it
		// as a column
		children = React.Children.toArray(children)
		let extra = children.find(child => child.type === FormFieldExtraCol)
		if (extra)
			children.splice(children.indexOf(extra), 1)

		// if type is static, render out a static value
		if (this.props.type === 'static' || (!this.props.type && !this.props.componentClass && this.context.form.props.static)) {
			children = <FormControl.Static componentClass={'div'} id={id} {...childProps}>{(children.length && children) || defaultValue}</FormControl.Static>

		// if children are provided, render those, but special case them to
		// automatically set value and children props
		} else if (!this.props.componentClass && children.length) {
			children = children.map(child => {
				let propTypes = child.type.propTypes

				// check to see if this is some kind of element where we
				// can register an onChange handler, otherwise skip it
				if (propTypes && !propTypes.onChange)
					return child

				let onChange = child.props.onChange || this.onChange
				return React.cloneElement(child, {value: defaultValue, onChange: onChange, onInput: onChange})
			})

		// otherwise render out a default FormControl input element
		} else {
			if (children.length)
				childProps.children = children

			const formControl = <FormControl
				{...childProps}
				value={defaultValue}
				onChange={this.onChange}
				onInput={this.onChange}
				onBlur={this.onUserTouchedField} />

			children =

				{formControl}
				<HelpBlock className={validationState === 'error' || validationState === 'warning' ? '' : 'hidden'} >
					{this.props.humanName} is required
				</HelpBlock>

		}

		if (icon) {
			icon =
		}

		// if there's an addon we need to use an InputGroup
		if (addon) {
			// allows passing a url for an image
			if (addon.indexOf('.') !== -1) {
				addon =
			}

			children =

				<InputGroup>
					{children}
					<InputGroup.Addon onClick={this.focus}>{addon}</InputGroup.Addon>
				</InputGroup>
				{postInputGroupChildren}

		}

		return (
			<FormGroup controlId={id} className={className} validationState={validationState}>
				{horizontal
					? <Col sm={2} componentClass={ControlLabel}>{label} {icon}</Col>
					: <ControlLabel>{label} {icon}</ControlLabel> }
				{horizontal
					? <Col sm={7}>{children}</Col>
					: children }
				{extra}
			</FormGroup>
		)
	}

	@autobind
	isMissingRequiredField(props) {
		return props.required && !this.state.value && this.state.userHasTouchedField
	}

	shouldComponentUpdate(newProps, newState, newContext) {
		if (this.state.userHasTouchedField !== newState.userHasTouchedField) {
			return true
		}

		let newValue = this.getDefaultValue(newProps, newContext)
		let oldValue = this.state.value

		if (newValue !== oldValue) {
			return true
		}

		if (Array.isArray(newValue)) {
			return !deepEqual(newValue, oldValue)
		}

		if (!deepEqual(this.props, newProps)) {
			return true
		}

		return false
	}

	getValue(props, context) {
		let formContext = context.formFor
		let id = props.id
		let getter = props.getter
		if (formContext) {
			let value = formContext[id]
			return getter ? getter(value) : value
		}
	}

	getDefaultValue(props, context) {
		return props.value || this.getValue(props, context) || ''
	}

	componentWillMount() {
		if (this.props.validateBeforeUserTouches) {
			this.setState({userHasTouchedField: true})
		}
	}

	componentWillReceiveProps(nextProps) {
		if (nextProps.validateBeforeUserTouches) {
			this.setState({userHasTouchedField: true})
		}

		if (nextProps.required !== this.props.required) {
			this.updateValidationState(nextProps)
		}
	}

	@autobind
	updateValidationState(props) {
		if (!this.state.userHasTouchedField) {
			return
		}

		this.setState({isValid: !this.isMissingRequiredField(props)})

		if (this.isMissingRequiredField(props) || this.state.isValid === false) {
			props.onError()
		} else if (props.onValid && !this.isMissingRequiredField(props) && this.state.isValid !== false) {
			props.onValid()
		}
	}

	@autobind
	onUserTouchedField(event) {
		this.setState({
			isValid: event && event.target ? event.target.checkValidity() : null,
			userHasTouchedField: true
		}, () => this.updateValidationState(this.props))
	}

	@autobind
	onChange(event) {
		if (this.props.onError || this.props.onValid || this.props.required) {
			this.onUserTouchedField(event)
		}

		if (this.props.onChange) {
			this.props.onChange(event)
			return
		}

		let id = this.props.id
		let value = event && event.target ? event.target.value : event

		if (this.props.maxCharacters && value.length > this.props.maxCharacters) {
			return
		}

		let formContext = this.context.formFor
		if (formContext)
			formContext[id] = value

		let form = this.context.form
		if (form && form.props.onChange) {
			form.props.onChange(event)
			event && event.stopPropagation && event.stopPropagation()
		}
	}

	@autobind
	focus() {
		let element = document.getElementById(this.props.id)
		if (element && element.focus) {
			element.focus()
		}
	}
}

FormField.ExtraCol = FormFieldExtraCol
<|endoftext|>


<commit_before>function mouseover() {

}
<commit_msg>tried to add mouseover  event<commit_after>var test =document.getElementById("test");
test.addEventListener("mouseover", function(event) {
	event.target.style.color= "red";

	setTimeout(function(){
	event.target.style.color= "";
	},500);

},false);

<|endoftext|>


<commit_before>import React from 'react';
import { shallow } from 'enzyme';
import CountrySelect from '../src/components/CountrySelect';
import en from '../src/i18n/en';

describe('CountrySelect', () => {
  let wrapper;
  const region = '';
  const onInputChange = jest.fn();
  const context = { language: en };

  beforeEach(() => {
    wrapper = shallow(<CountrySelect onInputChange={onInputChange} region={region} />, { context });
  });

  it('should be defined', () => {
    expect(wrapper).toBeDefined();
  });

  it('should render', () => {
    expect(wrapper.find('select').length).toBe(1);
  });

  it('should receive region prop', () => {
    expect(wrapper.props().region).toBe('');
  });

  it('should have onInputChange prop', () => {
    expect(wrapper.props().onInputChange).toBeDefined();
  });

  describe('user change option', () => {
    const input = wrapper.find('select').first();
    const value = 'sweden';

    beforeEach(() => {
      input.simulate('change', {
        target: { value },
      });
    });

    it('onInputChange should be called', () => {
      expect(onInputChange.mock.calls.length).toBe(1);
    });
  });
});
<commit_msg>:white_check_mark: added test spec<commit_after>import React from 'react';
import { mount } from 'enzyme';
import CountrySelect from '../src/components/CountrySelect';
import en from '../src/i18n/en';

describe('CountrySelect', () => {
  let wrapper;
  const region = '';
  const onInputChange = jest.fn();
  const context = { language: en };

  beforeEach(() => {
    wrapper = mount(<CountrySelect onInputChange={onInputChange} region={region} />, { context });
  });

  it('should be defined', () => {
    expect(wrapper).toBeDefined();
  });

  it('should render', () => {
    expect(wrapper.find('select').length).toBe(1);
  });

  it('should receive region prop', () => {
    expect(wrapper.props().region).toBe('');
  });

  it('should have prop region set as a defaultValue', () => {
    const select = wrapper.find('select').first();
    expect(select.props().defaultValue).toBe(region);
  });

  it('should have onInputChange prop', () => {
    expect(wrapper.props().onInputChange).toBeDefined();
  });

  describe('user change option', () => {
    const input = wrapper.find('select').first();
    const value = 'sweden';

    beforeEach(() => {
      input.simulate('change', {
        target: { value },
      });
    });

    it('onInputChange should be called', () => {
      expect(onInputChange.mock.calls.length).toBe(1);
    });
  });
});
<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2022
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

"use strict";

(function(window)
{
	/**
	 * Класс, представляющий элемент списка Combobox или DropDownList
	 * @constructor
	 */
	function CSdtListItem()
	{
		this.DisplayText = "";
		this.Value       = "";
	}
	CSdtListItem.prototype.Copy = function()
	{
		var oItem = new CSdtListItem();
		oItem.DisplayText = this.DisplayText;
		oItem.Value       = this.Value;
		return oItem;
	};
	CSdtListItem.prototype.IsEqual = function(oItem)
	{
		return (this.DisplayText === oItem.DisplayText && this.Value === oItem.Value);
	};
	CSdtListItem.prototype.WriteToBinary = function(oWriter)
	{
		oWriter.WriteString2(this.DisplayText);
		oWriter.WriteString2(this.Value);
	};
	CSdtListItem.prototype.ReadFromBinary = function(oReader)
	{
		this.DisplayText = oReader.GetString2();
		this.Value       = oReader.GetString2();
	};

	/**
	 * Класс с настройками для выпадающего списка
	 * @constructor
	 */
	function CSdtComboBoxPr()
	{
		this.ListItems = [];
		this.LastValue = -1;
		this.AutoFit   = false;
		this.Format    = new AscWord.CTextFormFormat();
	}
	CSdtComboBoxPr.prototype.Copy = function()
	{
		var oList = new CSdtComboBoxPr();

		oList.LastValue = this.LastValue;
		oList.ListItems = [];

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			oList.ListItems.push(this.ListItems[nIndex].Copy());
		}

		oList.AutoFit = this.AutoFit;

		return oList;
	};
	CSdtComboBoxPr.prototype.IsEqual = function(oOther)
	{
		if (!oOther || this.LastValue !== oOther.LastValue || this.ListItems.length !== oOther.ListItems.length)
			return false;

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (!this.ListItems[nIndex].IsEqual(oOther.ListItems[nIndex]))
				return false;
		}

		return true;
	};
	CSdtComboBoxPr.prototype.AddItem = function(sDisplay, sValue)
	{
		if (null !== this.GetTextByValue(sValue))
			return false;

		var oItem = new CSdtListItem();
		oItem.DisplayText = sDisplay;
		oItem.Value       = sValue;
		this.ListItems.push(oItem);

		return true;
	};
	CSdtComboBoxPr.prototype.Clear = function()
	{
		this.ListItems = [];
		this.LastValue = -1;
	};
	CSdtComboBoxPr.prototype.GetTextByValue = function(sValue)
	{
		if (!sValue || "" === sValue)
			return null;

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (this.ListItems[nIndex].Value === sValue)
				return this.ListItems[nIndex].DisplayText;
		}

		return null;
	};
	CSdtComboBoxPr.prototype.WriteToBinary = function(oWriter)
	{
		oWriter.WriteLong(this.LastValue);
		oWriter.WriteLong(this.ListItems.length);
		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			this.ListItems[nIndex].WriteToBinary(oWriter);
		}
		oWriter.WriteBool(this.AutoFit);
		this.Format.WriteToBinary(oWriter);
	};
	CSdtComboBoxPr.prototype.ReadFromBinary = function(oReader)
	{
		this.LastValue = oReader.GetLong();

		var nCount = oReader.GetLong();
		for (var nIndex = 0; nIndex < nCount; ++nIndex)
		{
			var oItem = new CSdtListItem();
			oItem.ReadFromBinary(oReader);
			this.ListItems.push(oItem);
		}
		this.AutoFit = oReader.GetBool();
		this.Format.ReadFromBinary(oReader);
	};
	CSdtComboBoxPr.prototype.Write_ToBinary = function(oWriter)
	{
		this.WriteToBinary(oWriter);
	};
	CSdtComboBoxPr.prototype.Read_FromBinary = function(oReader)
	{
		this.ReadFromBinary(oReader);
	};
	CSdtComboBoxPr.prototype.GetItemsCount = function()
	{
		return this.ListItems.length;
	};
	CSdtComboBoxPr.prototype.GetItemDisplayText = function(nIndex)
	{
		if (!this.ListItems[nIndex])
			return "";

		return this.ListItems[nIndex].DisplayText;
	};
	CSdtComboBoxPr.prototype.GetItemValue = function(nIndex)
	{
		if (!this.ListItems[nIndex])
			return "";

		return this.ListItems[nIndex].Value;
	};
	CSdtComboBoxPr.prototype.FindByText = function(sValue)
	{
		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (this.ListItems[nIndex].DisplayText === sValue)
				return nIndex;
		}

		return -1;
	};
	CSdtComboBoxPr.prototype.GetAutoFit = function()
	{
		return this.AutoFit;
	};
	CSdtComboBoxPr.prototype.SetAutoFit = function(isAutoFit)
	{
		this.AutoFit = isAutoFit;
	};
	CSdtComboBoxPr.prototype.GetFormat = function()
	{
		return this.Format;
	};
	//--------------------------------------------------------export----------------------------------------------------
	window['AscWord'] = window['AscWord'] || {};
	window['AscWord'].CSdtComboBoxPr = CSdtComboBoxPr;
	window['AscWord'].CSdtListItem   = CSdtListItem;

	window['AscCommon'].CSdtComboBoxPr    = CSdtComboBoxPr;
	window['AscCommon']['CSdtComboBoxPr'] = CSdtComboBoxPr;

	CSdtComboBoxPr.prototype['add_Item']            = CSdtComboBoxPr.prototype.AddItem;
	CSdtComboBoxPr.prototype['clear']               = CSdtComboBoxPr.prototype.Clear;
	CSdtComboBoxPr.prototype['get_TextByValue']     = CSdtComboBoxPr.prototype.GetTextByValue;
	CSdtComboBoxPr.prototype['get_ItemsCount']      = CSdtComboBoxPr.prototype.GetItemsCount;
	CSdtComboBoxPr.prototype['get_ItemDisplayText'] = CSdtComboBoxPr.prototype.GetItemDisplayText;
	CSdtComboBoxPr.prototype['get_ItemValue']       = CSdtComboBoxPr.prototype.GetItemValue;
	CSdtComboBoxPr.prototype['put_AutoFit']         = CSdtComboBoxPr.prototype.GetAutoFit;
	CSdtComboBoxPr.prototype['put_AutoFit']         = CSdtComboBoxPr.prototype.SetAutoFit;

})(window);
<commit_msg>[de] Add format check for combobox when copying<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2022
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

"use strict";

(function(window)
{
	/**
	 * Класс, представляющий элемент списка Combobox или DropDownList
	 * @constructor
	 */
	function CSdtListItem()
	{
		this.DisplayText = "";
		this.Value       = "";
	}
	CSdtListItem.prototype.Copy = function()
	{
		var oItem = new CSdtListItem();
		oItem.DisplayText = this.DisplayText;
		oItem.Value       = this.Value;
		return oItem;
	};
	CSdtListItem.prototype.IsEqual = function(oItem)
	{
		return (this.DisplayText === oItem.DisplayText && this.Value === oItem.Value);
	};
	CSdtListItem.prototype.WriteToBinary = function(oWriter)
	{
		oWriter.WriteString2(this.DisplayText);
		oWriter.WriteString2(this.Value);
	};
	CSdtListItem.prototype.ReadFromBinary = function(oReader)
	{
		this.DisplayText = oReader.GetString2();
		this.Value       = oReader.GetString2();
	};

	/**
	 * Класс с настройками для выпадающего списка
	 * @constructor
	 */
	function CSdtComboBoxPr()
	{
		this.ListItems = [];
		this.LastValue = -1;
		this.AutoFit   = false;
		this.Format    = new AscWord.CTextFormFormat();
	}
	CSdtComboBoxPr.prototype.Copy = function()
	{
		var oList = new CSdtComboBoxPr();

		oList.LastValue = this.LastValue;
		oList.ListItems = [];

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			oList.ListItems.push(this.ListItems[nIndex].Copy());
		}

		oList.AutoFit = this.AutoFit;
		oList.Format  = this.Format.Copy();

		return oList;
	};
	CSdtComboBoxPr.prototype.IsEqual = function(oOther)
	{
		if (!oOther
			|| this.LastValue !== oOther.LastValue
			|| this.ListItems.length !== oOther.ListItems.length
			|| !this.Format.IsEqual(oOther.Format))
			return false;

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (!this.ListItems[nIndex].IsEqual(oOther.ListItems[nIndex]))
				return false;
		}

		return true;
	};
	CSdtComboBoxPr.prototype.AddItem = function(sDisplay, sValue)
	{
		if (null !== this.GetTextByValue(sValue))
			return false;

		var oItem = new CSdtListItem();
		oItem.DisplayText = sDisplay;
		oItem.Value       = sValue;
		this.ListItems.push(oItem);

		return true;
	};
	CSdtComboBoxPr.prototype.Clear = function()
	{
		this.ListItems = [];
		this.LastValue = -1;
	};
	CSdtComboBoxPr.prototype.GetTextByValue = function(sValue)
	{
		if (!sValue || "" === sValue)
			return null;

		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (this.ListItems[nIndex].Value === sValue)
				return this.ListItems[nIndex].DisplayText;
		}

		return null;
	};
	CSdtComboBoxPr.prototype.WriteToBinary = function(oWriter)
	{
		oWriter.WriteLong(this.LastValue);
		oWriter.WriteLong(this.ListItems.length);
		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			this.ListItems[nIndex].WriteToBinary(oWriter);
		}
		oWriter.WriteBool(this.AutoFit);
		this.Format.WriteToBinary(oWriter);
	};
	CSdtComboBoxPr.prototype.ReadFromBinary = function(oReader)
	{
		this.LastValue = oReader.GetLong();

		var nCount = oReader.GetLong();
		for (var nIndex = 0; nIndex < nCount; ++nIndex)
		{
			var oItem = new CSdtListItem();
			oItem.ReadFromBinary(oReader);
			this.ListItems.push(oItem);
		}
		this.AutoFit = oReader.GetBool();
		this.Format.ReadFromBinary(oReader);
	};
	CSdtComboBoxPr.prototype.Write_ToBinary = function(oWriter)
	{
		this.WriteToBinary(oWriter);
	};
	CSdtComboBoxPr.prototype.Read_FromBinary = function(oReader)
	{
		this.ReadFromBinary(oReader);
	};
	CSdtComboBoxPr.prototype.GetItemsCount = function()
	{
		return this.ListItems.length;
	};
	CSdtComboBoxPr.prototype.GetItemDisplayText = function(nIndex)
	{
		if (!this.ListItems[nIndex])
			return "";

		return this.ListItems[nIndex].DisplayText;
	};
	CSdtComboBoxPr.prototype.GetItemValue = function(nIndex)
	{
		if (!this.ListItems[nIndex])
			return "";

		return this.ListItems[nIndex].Value;
	};
	CSdtComboBoxPr.prototype.FindByText = function(sValue)
	{
		for (var nIndex = 0, nCount = this.ListItems.length; nIndex < nCount; ++nIndex)
		{
			if (this.ListItems[nIndex].DisplayText === sValue)
				return nIndex;
		}

		return -1;
	};
	CSdtComboBoxPr.prototype.GetAutoFit = function()
	{
		return this.AutoFit;
	};
	CSdtComboBoxPr.prototype.SetAutoFit = function(isAutoFit)
	{
		this.AutoFit = isAutoFit;
	};
	CSdtComboBoxPr.prototype.GetFormat = function()
	{
		return this.Format;
	};
	//--------------------------------------------------------export----------------------------------------------------
	window['AscWord'] = window['AscWord'] || {};
	window['AscWord'].CSdtComboBoxPr = CSdtComboBoxPr;
	window['AscWord'].CSdtListItem   = CSdtListItem;

	window['AscCommon'].CSdtComboBoxPr    = CSdtComboBoxPr;
	window['AscCommon']['CSdtComboBoxPr'] = CSdtComboBoxPr;

	CSdtComboBoxPr.prototype['add_Item']            = CSdtComboBoxPr.prototype.AddItem;
	CSdtComboBoxPr.prototype['clear']               = CSdtComboBoxPr.prototype.Clear;
	CSdtComboBoxPr.prototype['get_TextByValue']     = CSdtComboBoxPr.prototype.GetTextByValue;
	CSdtComboBoxPr.prototype['get_ItemsCount']      = CSdtComboBoxPr.prototype.GetItemsCount;
	CSdtComboBoxPr.prototype['get_ItemDisplayText'] = CSdtComboBoxPr.prototype.GetItemDisplayText;
	CSdtComboBoxPr.prototype['get_ItemValue']       = CSdtComboBoxPr.prototype.GetItemValue;
	CSdtComboBoxPr.prototype['put_AutoFit']         = CSdtComboBoxPr.prototype.GetAutoFit;
	CSdtComboBoxPr.prototype['put_AutoFit']         = CSdtComboBoxPr.prototype.SetAutoFit;

})(window);
<|endoftext|>


<commit_before>kiwi.model.Panel = Backbone.Model.extend({
    initialize: function (attributes) {
        var name = this.get("name") || "";
        this.view = new kiwi.view.Panel({"model": this, "name": name});
        this.set({
            "scrollback": [],
            "name": name
        }, {"silent": true});
    },

    addMsg: function (nick, msg, type, opts) {
        var message_obj, bs, d;

        opts = opts || {};

        // Time defaults to now
        if (!opts || typeof opts.time === 'undefined') {
            d = new Date();
            opts.time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
        }

        // CSS style defaults to empty string
        if (!opts || typeof opts.style === 'undefined') {
            opts.style = '';
        }

        // Run through the plugins
        message_obj = {"msg": msg, "time": opts.time, "nick": nick, "chan": this.get("name"), "type": type, "style": opts.style};
        //tmp = kiwi.plugs.run('addmsg', message_obj);
        if (!message_obj) {
            return;
        }

        // The CSS class (action, topic, notice, etc)
        if (typeof message_obj.type !== "string") {
            message_obj.type = '';
        }

        // Make sure we don't have NaN or something
        if (typeof message_obj.msg !== "string") {
            message_obj.msg = '';
        }

        // Update the scrollback
        bs = this.get("scrollback");
        bs.push(message_obj);

        // Keep the scrolback limited
        if (bs.length > 250) {
            bs.splice(250);
        }
        this.set({"scrollback": bs}, {silent: true});

        this.trigger("msg", message_obj);
    },

    closePanel: function () {
        if (this.view) {
            this.view.remove();
            delete this.view;
        }

        var members = this.get('members');
        if (members) {
            members.reset([]);
            this.unset('members');
        }

        this.unbind();
        this.destroy();

        // If closing the active panel, switch to the server panel
        if (this.cid === kiwi.app.panels.active.cid) {
            kiwi.app.panels.server.view.show();
        }
    },

    // Alias to closePanel() for child objects to override
    close: function () {
        return this.closePanel();
    },

    isChannel: function () {
        var channel_prefix = kiwi.gateway.get('channel_prefix'),
            this_name = this.get('name');

        if (this.isApplet() || !this_name) return false;
        return (channel_prefix.indexOf(this_name[0]) > -1);
    },

    isApplet: function () {
        return this.applet ? true : false;
    },

    isServer: function () {
        return this.server ? true : false;
    }
});<commit_msg>Removing Panels properly<commit_after>kiwi.model.Panel = Backbone.Model.extend({
    initialize: function (attributes) {
        var name = this.get("name") || "";
        this.view = new kiwi.view.Panel({"model": this, "name": name});
        this.set({
            "scrollback": [],
            "name": name
        }, {"silent": true});
    },

    addMsg: function (nick, msg, type, opts) {
        var message_obj, bs, d;

        opts = opts || {};

        // Time defaults to now
        if (!opts || typeof opts.time === 'undefined') {
            d = new Date();
            opts.time = d.getHours().toString().lpad(2, "0") + ":" + d.getMinutes().toString().lpad(2, "0") + ":" + d.getSeconds().toString().lpad(2, "0");
        }

        // CSS style defaults to empty string
        if (!opts || typeof opts.style === 'undefined') {
            opts.style = '';
        }

        // Run through the plugins
        message_obj = {"msg": msg, "time": opts.time, "nick": nick, "chan": this.get("name"), "type": type, "style": opts.style};
        //tmp = kiwi.plugs.run('addmsg', message_obj);
        if (!message_obj) {
            return;
        }

        // The CSS class (action, topic, notice, etc)
        if (typeof message_obj.type !== "string") {
            message_obj.type = '';
        }

        // Make sure we don't have NaN or something
        if (typeof message_obj.msg !== "string") {
            message_obj.msg = '';
        }

        // Update the scrollback
        bs = this.get("scrollback");
        bs.push(message_obj);

        // Keep the scrolback limited
        if (bs.length > 250) {
            bs.splice(250);
        }
        this.set({"scrollback": bs}, {silent: true});

        this.trigger("msg", message_obj);
    },

    closePanel: function () {
        if (this.view) {
            this.view.remove();
            delete this.view;
        }

        var members = this.get('members');
        if (members) {
            members.reset([]);
            this.unset('members');
        }

        kiwi.app.panels.remove(this);

        this.unbind();
        this.destroy();

        // If closing the active panel, switch to the server panel
        if (this.cid === kiwi.app.panels.active.cid) {
            kiwi.app.panels.server.view.show();
        }
    },

    // Alias to closePanel() for child objects to override
    close: function () {
        return this.closePanel();
    },

    isChannel: function () {
        var channel_prefix = kiwi.gateway.get('channel_prefix'),
            this_name = this.get('name');

        if (this.isApplet() || !this_name) return false;
        return (channel_prefix.indexOf(this_name[0]) > -1);
    },

    isApplet: function () {
        return this.applet ? true : false;
    },

    isServer: function () {
        return this.server ? true : false;
    }
});<|endoftext|>


<commit_before>// The MPUtil object provides routines that are used multiple times in the
// page-specific JS code. It mostly contains functions for rendering result sets
// as returned by MPAjax into HTML.

var MPUtil = (function() {
    var shortWeekdays = [
        "Sun",
        "Mon",
        "Tue",
        "Wed",
        "Thu",
        "Fri",
        "Sat",
    ];

    var shortMonths = [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
    ];

    var MPUtil = {};

    function zeroPad(str, length) {
        str = "" + str;
        while (str.length < length) {
            str = "0" + str;
        }
        return str;
    }

    // Renders a single meal/tag result and returns the created
 element.
    // Used by MPUtil.renderMealList.
    function renderMealResult(mt, score, callback) {
        var row = $("
");
        var nameCell = $("").appendTo(row);

        if (MPUtil.nonNull(callback)) {
            $("").text(mt.meal.name).appendTo(nameCell).click(function(event) {
                event.preventDefault();
                callback(mt);
            });
        }
        else {
            nameCell.text(mt.meal.name);
        }

        $("").appendTo(row).text((mt.tags || []).join(", "));

        if (MPUtil.nonNull(score)) {
            $("").text(score).appendTo(row);
        }

        $("<button title='Open the recipe page listed for this meal' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                location.href = mt.meal.recipe;
            });

        var favButton   = $("<button title='Mark this meal as a favourite' class='action-button'></button>");
        var unfavButton = $("<button title='Remove the favourite mark from this meal' class='action-button'></button>");

        favButton.click(function(event) {
            event.preventDefault();

            MPAjax.toggleFavourite(mt.meal.id, function(isFavourite) {
                if (isFavourite) {
                    favButton.hide();
                    unfavButton.show();
                }
                else {
                    alert("Unexpected: 'favourite' button did not favourite the meal!");
                }
            });
        });

        unfavButton.click(function(event) {
            event.preventDefault();

            MPAjax.toggleFavourite(mt.meal.id, function(isFavourite) {
                if (!isFavourite) {
                    unfavButton.hide();
                    favButton.show();
                }
                else {
                    alert("Unexpected: 'unfavourite' button did not unfavourite the meal!");
                }
            })
        });

        if (mt.meal.favourite) {
            favButton.hide();
        }
        else {
            unfavButton.hide();
        }

        $("").appendTo(row).append(favButton).append(unfavButton);

        $("<button title='Edit this meal' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                location.href = "/meals/" + mt.meal.id + "/edit";
            });

        $("<button title='Delete this meal from the list' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                var row = $(this);

                MPAjax.deleteMeal(mt.meal.id, function(response) {
                    row.remove();
                });
            });

        return row;
    }

    // Takes a list of meal/tag results (as returned by MPAjax.fetchMealList)
    // and renders them to a table created inside 'container'. 'callback', if
    // not null, is a function that will be called when the meal name is clicked.
    // It is passed the meal-with-tags object.
    MPUtil.renderMealList = function(mts, container, callback) {
        mts = mts || [];
        container.empty();

        if (mts.length == 0) {
            container.text("No results to display.");
            return;
        }

        var table = $("
").appendTo(container);
        var thead = $("
").appendTo(table);
        var headerRow = $("
").appendTo(thead);
        $("Name	").appendTo(headerRow);
        $("Tags	").appendTo(headerRow);
        $("Actions	").appendTo(headerRow);
        var tbody = $("
").appendTo(table);

        var i, result, row;

        for (i = 0; i < mts.length; i++) {
            row = renderMealResult(mts[i], null, callback);
            row.appendTo(tbody);
        }
    };

    MPUtil.renderSuggestions = function(suggs, container, callback) {
        suggs = suggs || [];
        container.empty();

        if (suggs.length == 0) {
            container.text("No results to display.");
            return;
        }

        var table = $("
").appendTo(container);
        var thead = $("
").appendTo(table);
        var headerRow = $("
").appendTo(thead);
        $("Name	").appendTo(headerRow);
        $("Tags	").appendTo(headerRow);
        $("Score	").appendTo(headerRow);
        $("Actions	").appendTo(headerRow);
        var tbody = $("
").appendTo(table);

        var i, result, row;

        for (i = 0; i < suggs.length; i++) {
            row = renderMealResult(suggs[i].mt, 1.0 * suggs[i].score, callback);
            row.appendTo(tbody);
        }
    };

    // Takes a list of tags (as returned by MPAjax.fetchAllTags) and renders
    // them to the <select> tag 'container'.
    MPUtil.renderExistingTagsList = function(tags, container) {
        tags = tags || [];

        var i, tag;
        for (i = 0; i < tags.length; i++) {
            tag = tags[i];
            $("<option>").val(tag).text(tag).appendTo(container);
        }
    };

    MPUtil.formatMonthHumanReadable = function(date) {
        return shortMonths[date.getMonth()] + " " + date.getFullYear();
    };

    MPUtil.formatDateHumanReadable = function(date) {
        return shortWeekdays[date.getDay()] + " " + date.getDate() + " " + shortMonths[date.getMonth()];
    };

    MPUtil.formatDateJSON = function(date) {
        return zeroPad(date.getFullYear(), 4) + "-" + zeroPad(date.getMonth() + 1, 2) + "-" + zeroPad(date.getDate(), 2);
    };

    MPUtil.nonNull = function(value) {
        return typeof value !== "undefined" && value !== null;
    };

    return MPUtil;
})();
<commit_msg>Add confirmation to meal deletion<commit_after>// The MPUtil object provides routines that are used multiple times in the
// page-specific JS code. It mostly contains functions for rendering result sets
// as returned by MPAjax into HTML.

var MPUtil = (function() {
    var shortWeekdays = [
        "Sun",
        "Mon",
        "Tue",
        "Wed",
        "Thu",
        "Fri",
        "Sat",
    ];

    var shortMonths = [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
    ];

    var MPUtil = {};

    function zeroPad(str, length) {
        str = "" + str;
        while (str.length < length) {
            str = "0" + str;
        }
        return str;
    }

    // Renders a single meal/tag result and returns the created
 element.
    // Used by MPUtil.renderMealList.
    function renderMealResult(mt, score, callback) {
        var row = $("
");
        var nameCell = $("").appendTo(row);

        if (MPUtil.nonNull(callback)) {
            $("").text(mt.meal.name).appendTo(nameCell).click(function(event) {
                event.preventDefault();
                callback(mt);
            });
        }
        else {
            nameCell.text(mt.meal.name);
        }

        $("").appendTo(row).text((mt.tags || []).join(", "));

        if (MPUtil.nonNull(score)) {
            $("").text(score).appendTo(row);
        }

        $("<button title='Open the recipe page listed for this meal' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                location.href = mt.meal.recipe;
            });

        var favButton   = $("<button title='Mark this meal as a favourite' class='action-button'></button>");
        var unfavButton = $("<button title='Remove the favourite mark from this meal' class='action-button'></button>");

        favButton.click(function(event) {
            event.preventDefault();

            MPAjax.toggleFavourite(mt.meal.id, function(isFavourite) {
                if (isFavourite) {
                    favButton.hide();
                    unfavButton.show();
                }
                else {
                    alert("Unexpected: 'favourite' button did not favourite the meal!");
                }
            });
        });

        unfavButton.click(function(event) {
            event.preventDefault();

            MPAjax.toggleFavourite(mt.meal.id, function(isFavourite) {
                if (!isFavourite) {
                    unfavButton.hide();
                    favButton.show();
                }
                else {
                    alert("Unexpected: 'unfavourite' button did not unfavourite the meal!");
                }
            })
        });

        if (mt.meal.favourite) {
            favButton.hide();
        }
        else {
            unfavButton.hide();
        }

        $("").appendTo(row).append(favButton).append(unfavButton);

        $("<button title='Edit this meal' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                location.href = "/meals/" + mt.meal.id + "/edit";
            });

        $("<button title='Delete this meal from the list' class='action-button'></button>	")
            .appendTo(row)
            .click(function(event) {
                event.preventDefault();
                var row = $(this);

                if (confirm("Are you sure you want to delete the meal '" + mt.meal.name + "'?")) {
                    MPAjax.deleteMeal(mt.meal.id, function(response) {
                        row.remove();
                    });
                }
            });

        return row;
    }

    // Takes a list of meal/tag results (as returned by MPAjax.fetchMealList)
    // and renders them to a table created inside 'container'. 'callback', if
    // not null, is a function that will be called when the meal name is clicked.
    // It is passed the meal-with-tags object.
    MPUtil.renderMealList = function(mts, container, callback) {
        mts = mts || [];
        container.empty();

        if (mts.length == 0) {
            container.text("No results to display.");
            return;
        }

        var table = $("
").appendTo(container);
        var thead = $("
").appendTo(table);
        var headerRow = $("
").appendTo(thead);
        $("Name	").appendTo(headerRow);
        $("Tags	").appendTo(headerRow);
        $("Actions	").appendTo(headerRow);
        var tbody = $("
").appendTo(table);

        var i, result, row;

        for (i = 0; i < mts.length; i++) {
            row = renderMealResult(mts[i], null, callback);
            row.appendTo(tbody);
        }
    };

    MPUtil.renderSuggestions = function(suggs, container, callback) {
        suggs = suggs || [];
        container.empty();

        if (suggs.length == 0) {
            container.text("No results to display.");
            return;
        }

        var table = $("
").appendTo(container);
        var thead = $("
").appendTo(table);
        var headerRow = $("
").appendTo(thead);
        $("Name	").appendTo(headerRow);
        $("Tags	").appendTo(headerRow);
        $("Score	").appendTo(headerRow);
        $("Actions	").appendTo(headerRow);
        var tbody = $("
").appendTo(table);

        var i, result, row;

        for (i = 0; i < suggs.length; i++) {
            row = renderMealResult(suggs[i].mt, 1.0 * suggs[i].score, callback);
            row.appendTo(tbody);
        }
    };

    // Takes a list of tags (as returned by MPAjax.fetchAllTags) and renders
    // them to the <select> tag 'container'.
    MPUtil.renderExistingTagsList = function(tags, container) {
        tags = tags || [];

        var i, tag;
        for (i = 0; i < tags.length; i++) {
            tag = tags[i];
            $("<option>").val(tag).text(tag).appendTo(container);
        }
    };

    MPUtil.formatMonthHumanReadable = function(date) {
        return shortMonths[date.getMonth()] + " " + date.getFullYear();
    };

    MPUtil.formatDateHumanReadable = function(date) {
        return shortWeekdays[date.getDay()] + " " + date.getDate() + " " + shortMonths[date.getMonth()];
    };

    MPUtil.formatDateJSON = function(date) {
        return zeroPad(date.getFullYear(), 4) + "-" + zeroPad(date.getMonth() + 1, 2) + "-" + zeroPad(date.getDate(), 2);
    };

    MPUtil.nonNull = function(value) {
        return typeof value !== "undefined" && value !== null;
    };

    return MPUtil;
})();
<|endoftext|>


<commit_before>var Q = require('q');

module.exports = {
    mapWaitlistDBVO : mapWaitlistDBVO,
    mapWaitlistItemDBVO : mapWaitlistItemDBVO,
    mapPilotDBVO : mapPilotDBVO
}

/*
 {
 "id": 4,
 "name": "Thomion`s waitlist",
 "externalId": "z5DapO3ksycMyMfj5Jm1impazAQHikBK",
 "createdAt": "2015-04-11T17:16:07.000Z",
 "updatedAt": "2015-04-11T17:16:07.000Z",
 "ownerId": "698922015",
 "items": []
 }
 {
 ownerId;
 waitlistId;
 ownerName;
 waitlistName;
 waitlist = [];
}
 */

function mapWaitlistDBVO(waitlist){
    var mapped = {};
    mapped.ownerId      = waitlist.ownerId;
    mapped.createdAt    = (new Date(waitlist.createdAt)).getTime();
    mapped.waitlistId   = waitlist.externalId;
    mapped.ownerName    = waitlist.owner ? waitlist.owner.name : '';
    mapped.waitlistName = waitlist.name;
    var items = waitlist.items ? waitlist.items.map(mapWaitlistItemDBVO) : [];
    return Q.all(items)
        .then(function (mappedItems) {
            mapped.waitlist = mappedItems;
            return mapPilotDBVO(waitlist.owner)
                .then(function (mappedPilot) {
                    mapped.owner = mappedPilot;
                    return mapped;
                })
        })
}

/*
 {
 "order": 3,
 "shipId": "001",
 "shipName": "Dicke Berta",
 "shipDNA": "003",
 "shipType": "002",
 "createdAt": "2015-04-11T17:59:11.000Z",
 "updatedAt": "2015-04-11T17:59:11.000Z",
 "pilotId": "698922015",
 "waitlistId": 4
 }
 {
 characterId;
 characterName;
 shipDNA;
 shipName;
 itemId;
 shipType;
 }
 */
function mapWaitlistItemDBVO(item){
    return item.getPilot()
        .then(function (pilot) {
            return mapPilotDBVO(pilot)
        })
        .then(function (mapped) {
            mapped.itemId    = item.order;
            mapped.createdAt = (new Date(item.createdAt)).getTime();
            return item.getFittings()
                .then(function (fittings) {
                    return fittings.map(mapShipFitting)
                })
                .then(function (mappedFittings) {
                    mapped.fittings = mappedFittings;
                    return mapped;
                })
        })
}

function mapShipFitting(fitting){
    var mapped = {};
    mapped.shipDNA  = fitting.dna;
    mapped.shipName = fitting.name;
    mapped.shipId   = fitting.shipId;
    mapped.shipType = fitting.type;
    mapped.role     = fitting.role;
    return mapped;
}

/*
 {
 "id": "698922015",
 "name": "Thomion",
 "createdAt": "2015-04-11T15:52:36.000Z",
 "updatedAt": "2015-04-11T19:25:29.000Z",
 "corpId": "1000006",
 "corp": {
 "id": "1000006",
 "name": "Deep Core Mining Inc.",
 "createdAt": "2015-04-11 15:54:39.000 +00:00",
 "updatedAt": "2015-04-11 15:54:39.000 +00:00",
 "allianceId": null,
 "alliance": null
 }
 }
    {
    characterId;
    characterName;
    corporationId;
    corporationName;
    allianceId;
    allianceName;
    }
 */

function mapPilotDBVO(pilot){
    var mapped = {};
    mapped.characterId  = pilot.id;
    mapped.characterName    = pilot.name;
    return pilot.getCorp()
        .then(function (corp) {
            mapped.corporationId    = corp.id;
            mapped.corporationName  = corp.name;
            return corp.getAlliance();
        })
        .then(function (alliance) {
            if(alliance){
                mapped.allianceId   = alliance.id;
                mapped.allianceName = alliance.name;
            }
            return mapped;
        })
}<commit_msg>fixed mapping<commit_after>var Q = require('q');

module.exports = {
    mapWaitlistDBVO : mapWaitlistDBVO,
    mapWaitlistItemDBVO : mapWaitlistItemDBVO,
    mapPilotDBVO : mapPilotDBVO
}

/*
 {
 "id": 4,
 "name": "Thomion`s waitlist",
 "externalId": "z5DapO3ksycMyMfj5Jm1impazAQHikBK",
 "createdAt": "2015-04-11T17:16:07.000Z",
 "updatedAt": "2015-04-11T17:16:07.000Z",
 "ownerId": "698922015",
 "items": []
 }
 {
 ownerId;
 waitlistId;
 ownerName;
 waitlistName;
 waitlist = [];
}
 */

function mapWaitlistDBVO(waitlist){
    var mapped = {};
    mapped.ownerId      = waitlist.ownerId;
    mapped.createdAt    = (new Date(waitlist.createdAt)).getTime();
    mapped.waitlistId   = waitlist.externalId;
    mapped.waitlistName = waitlist.name;

    var items = waitlist.items ? waitlist.items.map(mapWaitlistItemDBVO) : [];
    return Q.all(items)
        .then(function (mappedItems) {
            mapped.waitlist = mappedItems;
            return waitlist.getOwner();
        })
        .then(mapPilotDBVO)
        .then(function (mappedPilot) {
            mapped.owner = mappedPilot;
            return mapped;
        })
}

/*
 {
 "order": 3,
 "shipId": "001",
 "shipName": "Dicke Berta",
 "shipDNA": "003",
 "shipType": "002",
 "createdAt": "2015-04-11T17:59:11.000Z",
 "updatedAt": "2015-04-11T17:59:11.000Z",
 "pilotId": "698922015",
 "waitlistId": 4
 }
 {
 characterId;
 characterName;
 shipDNA;
 shipName;
 itemId;
 shipType;
 }
 */
function mapWaitlistItemDBVO(item){
    return item.getPilot()
        .then(function (pilot) {
            return mapPilotDBVO(pilot)
        })
        .then(function (mapped) {
            mapped.itemId    = item.order;
            mapped.createdAt = (new Date(item.createdAt)).getTime();
            return item.getFittings()
                .then(function (fittings) {
                    return fittings.map(mapShipFitting)
                })
                .then(function (mappedFittings) {
                    mapped.fittings = mappedFittings;
                    return mapped;
                })
        })
}

function mapShipFitting(fitting){
    var mapped = {};
    mapped.shipDNA  = fitting.dna;
    mapped.shipName = fitting.name;
    mapped.shipId   = fitting.shipId;
    mapped.shipType = fitting.type;
    mapped.role     = fitting.role;
    return mapped;
}

/*
 {
 "id": "698922015",
 "name": "Thomion",
 "createdAt": "2015-04-11T15:52:36.000Z",
 "updatedAt": "2015-04-11T19:25:29.000Z",
 "corpId": "1000006",
 "corp": {
 "id": "1000006",
 "name": "Deep Core Mining Inc.",
 "createdAt": "2015-04-11 15:54:39.000 +00:00",
 "updatedAt": "2015-04-11 15:54:39.000 +00:00",
 "allianceId": null,
 "alliance": null
 }
 }
    {
    characterId;
    characterName;
    corporationId;
    corporationName;
    allianceId;
    allianceName;
    }
 */

function mapPilotDBVO(pilot){
    var mapped = {};
    mapped.characterId  = pilot.id;
    mapped.characterName    = pilot.name;
    return pilot.getCorp()
        .then(function (corp) {
            mapped.corporationId    = corp.id;
            mapped.corporationName  = corp.name;
            return corp.getAlliance();
        })
        .then(function (alliance) {
            if(alliance){
                mapped.allianceId   = alliance.id;
                mapped.allianceName = alliance.name;
            }
            return mapped;
        })
}<|endoftext|>


<commit_before>/* global describe, it, xit, before, after */
/* jslint node: true, esnext: true */
'use strict';

const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect,
  should = chai.should(),
  path = require('path'),
  fs = require('fs'),
    FileScheme = require('../dist/FileScheme');

describe('file', () => {
  const scheme = new FileScheme();
  it('has name', () => assert.equal(scheme.name, 'file'));

  it('can get', () => {
    const aFile = path.join(__dirname, 'file_test.js');
    return scheme.get('file://' + aFile).then(s => assert.isDefined(s));
  });

  it('can stat', () => {
    const aFile = path.join(__dirname, 'file_test.js');
    return scheme.stat('file://' + aFile).then(s => assert.isDefined(s));
  });

  it('can delete', (done) => {
    const aFile = path.join(__dirname, 'file.tmp');
    fs.writeFileSync(aFile, 'someData');
    scheme.delete('file://' + aFile).then(s =>
      fs.stat(aFile, (err, stat) => {
        if (err) {
          done();
        }
      })
    );
  });

  it('can list', () => {
    const aDir = path.join(__dirname);
    return scheme.list('file://' + aDir).then(files => {
      assert.isAtLeast(files.indexOf('file_test.js'), 0);
    });
  });

  it('list error', () => {
    return scheme.list('file://unknown').then(files => assert.ok(undefined)).catch(reject => assert.ok(reject));
  });
});
<commit_msg>test: stat() size<commit_after>/* global describe, it, xit, before, after */
/* jslint node: true, esnext: true */
'use strict';

const chai = require('chai'),
  assert = chai.assert,
  expect = chai.expect,
  should = chai.should(),
  path = require('path'),
  fs = require('fs'),
    FileScheme = require('../dist/FileScheme');

describe('file', () => {
  const scheme = new FileScheme();
  it('has name', () => assert.equal(scheme.name, 'file'));

  it('can get', () => {
    const aFile = path.join(__dirname, 'file_test.js');
    return scheme.get('file://' + aFile).then(s => assert.isDefined(s));
  });

  it('can stat', () => {
    const aFile = path.join(__dirname, 'file_test.js');
    return scheme.stat('file://' + aFile).then(s => {
      assert.equal(s.size,1414);
      assert.isDefined(s); }
    );
  });

  it('can delete', (done) => {
    const aFile = path.join(__dirname, 'file.tmp');
    fs.writeFileSync(aFile, 'someData');
    scheme.delete('file://' + aFile).then(s =>
      fs.stat(aFile, (err, stat) => {
        if (err) {
          done();
        }
      })
    );
  });

  it('can list', () => {
    const aDir = path.join(__dirname);
    return scheme.list('file://' + aDir).then(files => {
      assert.isAtLeast(files.indexOf('file_test.js'), 0);
    });
  });

  it('list error', () => {
    return scheme.list('file://unknown').then(files => assert.ok(undefined)).catch(reject => assert.ok(reject));
  });
});
<|endoftext|>