<commit_before>angular
  .module('lift-ng', [])
  .service('plumbing', [ '$q', function($q){
    var defers = {};

    var create = function(id) {
      var q = $q.defer();
      defers[id] = q;
      return q;
    };

    var resolve = function(data, q) {
      if (data.success) {
        if (typeof data.data !== 'undefined') {
          inject(data.data);
          q.resolve(data.data);
        }
        else {
          q.resolve();
        }
      } else {
        q.reject(data.msg)
      }
      return q;
    };

    // Called by the LiftNgFutureActor when a Future is fulfilled
    var fulfill = function(data, id) {
      var theId = id || data.id;
      var q = defers[theId];
      if(typeof q !== "undefined" && q !== null) { // We found our awaiting defer/promise
        resolve(data, q);
        delete defers[theId];
      } else { // We arrived before the model which embeds us!
        resolve(data, create(theId));
      }
    };

    // Called to inject promises wherever our serializer encountered a Future
    var inject = function(model) {
      console.log(JSON.stringify(model));
      for(var k in model) {
        if(model[k] == null) {
          // Don't do anything, skip
        }
        // It is a future which we need to inject
        else if(model[k]["net.liftmodules.ng.Angular.future"]) {
          var id   = model[k]["net.liftmodules.ng.Angular.future"];
          var data = model[k].data;
          var msg  = model[k].msg;
          var q = defers[id];
          if(typeof q !== "undefined" && q !== null) { // The future resolved before we arrived here
            model[k] = q.promise;
            delete defers[id];
          } else if(data) { // The future had already RESOLVED at serialization time
            var d = $q.defer();
            d.resolve(data);
            model[k] = d.promise;
          } else if(msg) { // The future had already FAILED at serialization time
            var d = $q.defer();
            d.reject(msg);
            model[k] = d.promise;
          } else { // Promise/Future pending
            model[k] = create(id).promise;
          }
        }
        // Not a future, so check children
        else if(typeof model[k] === 'object') {
          inject(model[k]);
        }
      }
    };

    return {
      createDefer: create,
      resolve: resolve,
      fulfill: fulfill,
      inject: inject
    }
  }])
  .service('liftProxy', ['$http', '$q', 'plumbing', function ($http, $q, plumbing) {
    var svc = {
      request: function (requestData) {
        var req = requestData.name+'='+encodeURIComponent(JSON.stringify({data:requestData.data}));

        var post = function() {
          return $http.post(net_liftmodules_ng.endpoint(), req, {
            headers : {
              'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            }
          });
        };

        var resolve = function(response) {
          var data = response.data;

          // If there is no future ID, then we have our data and we're done.
          if(!data.futureId) {
            var defer = $q.defer();
            plumbing.resolve(data, defer);
            return defer.promise;
          }

          // Otherwise, we need to plumb out a promise
          else {
            var defer = plumbing.createDefer(data.futureId);
            return defer.promise;
          }
        };

        return post().then(resolve);
      }
    };

    return svc;
  }
]);<commit_msg>Removing a console.log<commit_after>angular
  .module('lift-ng', [])
  .service('plumbing', [ '$q', function($q){
    var defers = {};

    var create = function(id) {
      var q = $q.defer();
      defers[id] = q;
      return q;
    };

    var resolve = function(data, q) {
      if (data.success) {
        if (typeof data.data !== 'undefined') {
          inject(data.data);
          q.resolve(data.data);
        }
        else {
          q.resolve();
        }
      } else {
        q.reject(data.msg)
      }
      return q;
    };

    // Called by the LiftNgFutureActor when a Future is fulfilled
    var fulfill = function(data, id) {
      var theId = id || data.id;
      var q = defers[theId];
      if(typeof q !== "undefined" && q !== null) { // We found our awaiting defer/promise
        resolve(data, q);
        delete defers[theId];
      } else { // We arrived before the model which embeds us!
        resolve(data, create(theId));
      }
    };

    // Called to inject promises wherever our serializer encountered a Future
    var inject = function(model) {
      for(var k in model) {
        if(model[k] == null) {
          // Don't do anything, skip
        }
        // It is a future which we need to inject
        else if(model[k]["net.liftmodules.ng.Angular.future"]) {
          var id   = model[k]["net.liftmodules.ng.Angular.future"];
          var data = model[k].data;
          var msg  = model[k].msg;
          var q = defers[id];
          if(typeof q !== "undefined" && q !== null) { // The future resolved before we arrived here
            model[k] = q.promise;
            delete defers[id];
          } else if(data) { // The future had already RESOLVED at serialization time
            var d = $q.defer();
            d.resolve(data);
            model[k] = d.promise;
          } else if(msg) { // The future had already FAILED at serialization time
            var d = $q.defer();
            d.reject(msg);
            model[k] = d.promise;
          } else { // Promise/Future pending
            model[k] = create(id).promise;
          }
        }
        // Not a future, so check children
        else if(typeof model[k] === 'object') {
          inject(model[k]);
        }
      }
    };

    return {
      createDefer: create,
      resolve: resolve,
      fulfill: fulfill,
      inject: inject
    }
  }])
  .service('liftProxy', ['$http', '$q', 'plumbing', function ($http, $q, plumbing) {
    var svc = {
      request: function (requestData) {
        var req = requestData.name+'='+encodeURIComponent(JSON.stringify({data:requestData.data}));

        var post = function() {
          return $http.post(net_liftmodules_ng.endpoint(), req, {
            headers : {
              'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            }
          });
        };

        var resolve = function(response) {
          var data = response.data;

          // If there is no future ID, then we have our data and we're done.
          if(!data.futureId) {
            var defer = $q.defer();
            plumbing.resolve(data, defer);
            return defer.promise;
          }

          // Otherwise, we need to plumb out a promise
          else {
            var defer = plumbing.createDefer(data.futureId);
            return defer.promise;
          }
        };

        return post().then(resolve);
      }
    };

    return svc;
  }
]);<|endoftext|>


<commit_before>/**
 * Validate file exists
 * usage:
 *     file - String path of file to check
 */
function isValidFile(file) {
    try {
        return fs.statSync(file).isFile();
    } catch (err) {
        return false;
    }
}

/**
 * Default 404 handler
 */
respond404 = function (req, res) {
    res.writeHead(404, {
        "Content-Type": "text/plain"
    });
    res.write(req.url + " not found");
    res.end();
};

/**
 * Handles reading a resource file and piping the results to response stream
 * file - path to the resources
 * req - http request
 * res - http response
 */
respondImage = function(req, res) {
    fs = require("fs");
    url = require("url");
    reqpath = url.parse(req.url).pathname;
    file = path.join(resources, reqpath);
    rs = require("fs").createReadStream(file);
    rs.pipe(res);
    rs.on("error", function(errpipe) {
        console.error(errpipe);
        throw errpipe;
    });
    res.writeHead(200, {
        "Content-Type": "text/plain"
    });
    rs.on("end", function() {
        res.end();
    });
};

/**
 * Caches image to the destination directory, performing an image transformation
 * if appropriate first using the img-cache utility (see https://github.com/willmark/img-cache)
 */
handleImage = function(req, res) {
    file = url.parse(req.url).pathname;
    basename = path.basename(file);
    dstdir = path.dirname(path.join(resources, file));
console.log(Object.keys(module.exports));
    srcdir = config.srcdir;
    imgc = require("img-cache");
    imgc.cacheImage(srcdir, dstdir, basename, function(stat, err) {
        if (!stat) {
            console.log("not copied: " + err);
            respond404(req, res);
        } else {
            respondImage(req, res);
        }
    });
}

module.exports = function(req, res) {
    handleImage(req, res);
}
<commit_msg>Fixes #2<commit_after>/**
 * Validate file exists
 * usage:
 *     file - String path of file to check
 */
function isValidFile(file) {
    try {
        return fs.statSync(file).isFile();
    } catch (err) {
        return false;
    }
}

/**
 * Default 404 handler
 */
respond404 = function (req, res) {
    res.writeHead(404, {
        "Content-Type": "text/plain"
    });
    res.write(req.url + " not found");
    res.end();
};

/**
 * Handles reading a resource file and piping the results to response stream
 * file - path to the resources
 * req - http request
 * res - http response
 */
respondImage = function(req, res) {
    fs = require("fs");
    url = require("url");
    reqpath = url.parse(req.url).pathname;
    file = path.join(resources, reqpath);
    rs = require("fs").createReadStream(file);
    rs.pipe(res);
    rs.on("error", function(errpipe) {
        console.error(errpipe);
        throw errpipe;
    });
    res.writeHead(200, {
        "Content-Type": "text/plain"
    });
    rs.on("end", function() {
        res.end();
    });
};

/**
 * Caches image to the destination directory, performing an image transformation
 * if appropriate first using the img-cache utility (see https://github.com/willmark/img-cache)
 */
handleImage = function(req, res) {
    file = url.parse(req.url).pathname;
    basename = path.basename(file);
    dstdir = path.dirname(path.join(resources, file));
    srcdir = config.srcdir;
    imgc = require("img-cache");
    imgc.cacheImage(srcdir, dstdir, basename, function(stat, err) {
        if (!stat) {
            console.log("not copied: " + err);
            respond404(req, res);
        } else {
            respondImage(req, res);
        }
    });
}

module.exports = function(req, res) {
    handleImage(req, res);
}
<|endoftext|>


<commit_before>var gulp = require('gulp'),

    //css related
    sass = require('gulp-sass'),
	sourcemaps = require('gulp-sourcemaps'),
	prefix = require('gulp-autoprefixer'),
    combineMq = require('gulp-combine-mq'),

    //js related
    uglify = require('gulp-uglify'),
    concat = require('gulp-concat'),

    //Html related
    nunjucksRender = require('gulp-nunjucks-render'),
    htmlmin = require('gulp-htmlmin'),

    //sever related
    browserSync = require('browser-sync'),

    //Shared and misc
    svgstore = require('gulp-svgstore'),
    svgmin = require('gulp-svgmin'),
    rename = require('gulp-rename'),
    data = require('gulp-data'),

    //error control
    plumber = require('gulp-plumber');

var projectName = 'theft',
    dist = 'dist',
    scripts = projectName + '/scripts';

/* live reload */
gulp.task('browser-sync', function () {
   var files = [
      dist + '/*.html',
      dist + '/css/*.css',
      dist + '/img/*.png',
      dist + '/js/*.js'
   ];

   browserSync.init(files, {
      server: {
         baseDir: './' + dist
      },
      open: false
   });
});

gulp.task('browser-sync-open-browser', function () {
   var files = [
      dist + '/*.html',
      dist + '/css/*.css',
      dist + '/img/*.png',
      dist + '/js/*.js'
   ];

   browserSync.init(files, {
      server: {
         baseDir: './' + dist
      }
   });
});

/* style related components */
/* scss css */

// scssToCss
gulp.task('scssToCss', function () {
    gulp.src(projectName + '/scss/**/*.scss')
        .pipe(sourcemaps.init())
        .pipe(sass({
            outputStyle: 'compressed'
        }))
        .pipe(plumber())
        .pipe(combineMq({
            beautify: false
        }))
        .pipe(prefix('last 4 versions'))
        .pipe(sourcemaps.write('../sourceMaps_css'))
        .pipe(gulp.dest(dist + '/css/'));
});

// js compress
gulp.task('jsCompress', function () {
    gulp.src([
         scripts + '/mode-local.js',
         scripts + '/sys-var.js',
         scripts + '/main.js',
         scripts + '/game-page.js',
         scripts + '/greet.js'
        ])
        .pipe(concat('script.js'))
        .pipe(uglify())
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/js/'));
});
// js compress distribution version
gulp.task('jsCompressWeb', function () {
    gulp.src([
         scripts + '/mode-web.js',
         scripts + '/sys-var.js',
         scripts + '/main.js',
         scripts + '/game-page.js',
         scripts + '/greet.js'
        ])
        .pipe(concat('script.js'))
        .pipe(uglify())
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/js/'));
});

// nunjucks to html
gulp.task('nunjucks', function() {
 nunjucksRender.nunjucks.configure([projectName + '/nunjucks_templates/'],{ watch: false });

  // Gets .html and .nunjucks files in pages
  return gulp.src(projectName + '/nunjucks_pages/*.nunjucks')
  // Renders template with nunjucks
  .pipe(nunjucksRender({
      title:'Theft',
      moto:'GTA Cheats'
  }))
  .pipe(plumber())
  // output files in app folder
  .pipe(gulp.dest(dist))

});

// games to html
gulp.task('gameMake', function() {

 nunjucksRender.nunjucks.configure([projectName + '/nunjucks_templates/'],{ watch: false });

  // Gets .html and .nunjucks files in pages
  return gulp.src(projectName + '/game_pages/*.nunjucks')
  // Renders template with nunjucks
  .pipe(data(function() {
   return require('./theft/api/theftdb.json')
  }))
  .pipe(nunjucksRender({
      title:'Theft',
      moto:'GTA Cheats'
  }))
  .pipe(plumber())
  .pipe(htmlmin({collapseWhitespace: true}))
  // output files in app folder
  .pipe(gulp.dest(dist + '/games/'));

});

// copy paste content of public folder to dist
gulp.task('public', function() {
  gulp.src(projectName + '/public/*/*.**')
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/'));
});
gulp.task('publicBase', function() {
  gulp.src(projectName + '/public/*.**')
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/'));
});

/* svg sprites */
/* type 'gulp svgstore' in console */
var path = require('path');

gulp.task('svgstore', function () {
    return gulp
        .src(projectName + '/svgAssets/*.svg')
        .pipe(svgmin(function (file) {
            var prefix = path.basename(file.relative, path.extname(file.relative));
            return {
                plugins: [{
                    cleanupIDs: {
                        prefix: prefix + '-',
                        minify: true
                    }
                }]
            }
        }))
        .pipe(rename({prefix: 'icon-'}))
        .pipe(svgstore())
        .pipe(gulp.dest(projectName + '/nunjucks_templates/partials/'));
});

/* Watch for changes */
/* Generic */
gulp.task('watch',function(){
	gulp.watch(projectName + '/scss/**/*.scss',['scssToCss']);
	gulp.watch(projectName + '/scripts/*.js',['jsCompress']);
	gulp.watch(projectName + '/nunjucks_pages/*.nunjucks',['nunjucks']);
	gulp.watch(projectName + '/nunjucks_templates/**/*.nunjucks',['nunjucks']);
	gulp.watch(projectName + '/game_pages/*.nunjucks',['gameMake']);
});

/* Default Gulp task */
/* type Gulp in console */

/* Local Testing */
gulp.task('default', ['scssToCss','jsCompress','browser-sync','nunjucks','gameMake','watch']);
gulp.task('openbrowser', ['scssToCss','jsCompress','svgstore','public','publicBase','browser-sync-open-browser','nunjucks','gameMake','watch']);

/* distribution version */
gulp.task('web', ['scssToCss','jsCompressWeb','browser-sync','nunjucks','gameMake','watch']);

<commit_msg>source maps removed for gulp web<commit_after>var gulp = require('gulp'),

    //css related
    sass = require('gulp-sass'),
	sourcemaps = require('gulp-sourcemaps'),
	prefix = require('gulp-autoprefixer'),
    combineMq = require('gulp-combine-mq'),

    //js related
    uglify = require('gulp-uglify'),
    concat = require('gulp-concat'),

    //Html related
    nunjucksRender = require('gulp-nunjucks-render'),
    htmlmin = require('gulp-htmlmin'),

    //sever related
    browserSync = require('browser-sync'),

    //Shared and misc
    svgstore = require('gulp-svgstore'),
    svgmin = require('gulp-svgmin'),
    rename = require('gulp-rename'),
    data = require('gulp-data'),

    //error control
    plumber = require('gulp-plumber');

var projectName = 'theft',
    dist = 'dist',
    scripts = projectName + '/scripts';

/* live reload */
gulp.task('browser-sync', function () {
   var files = [
      dist + '/*.html',
      dist + '/css/*.css',
      dist + '/img/*.png',
      dist + '/js/*.js'
   ];

   browserSync.init(files, {
      server: {
         baseDir: './' + dist
      },
      open: false
   });
});

gulp.task('browser-sync-open-browser', function () {
   var files = [
      dist + '/*.html',
      dist + '/css/*.css',
      dist + '/img/*.png',
      dist + '/js/*.js'
   ];

   browserSync.init(files, {
      server: {
         baseDir: './' + dist
      }
   });
});

/* style related components */
/* scss css */

// scssToCss
gulp.task('scssToCss', function () {
    gulp.src(projectName + '/scss/**/*.scss')
        .pipe(sourcemaps.init())
        .pipe(sass({
            outputStyle: 'compressed'
        }))
        .pipe(plumber())
        .pipe(combineMq({
            beautify: false
        }))
        .pipe(prefix('last 4 versions'))
        .pipe(sourcemaps.write('../sourceMaps_css'))
        .pipe(gulp.dest(dist + '/css/'));
});

// scssToCss
gulp.task('scssToCssWeb', function () {
    gulp.src(projectName + '/scss/**/*.scss')
        .pipe(sass({
            outputStyle: 'compressed'
        }))
        .pipe(plumber())
        .pipe(combineMq({
            beautify: false
        }))
        .pipe(prefix('last 4 versions'))
        .pipe(gulp.dest(dist + '/css/'));
});

// js compress
gulp.task('jsCompress', function () {
    gulp.src([
         scripts + '/mode-local.js',
         scripts + '/sys-var.js',
         scripts + '/main.js',
         scripts + '/game-page.js',
         scripts + '/greet.js'
        ])
        .pipe(concat('script.js'))
        .pipe(uglify())
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/js/'));
});
// js compress distribution version
gulp.task('jsCompressWeb', function () {
    gulp.src([
         scripts + '/mode-web.js',
         scripts + '/sys-var.js',
         scripts + '/main.js',
         scripts + '/game-page.js',
         scripts + '/greet.js'
        ])
        .pipe(concat('script.js'))
        .pipe(uglify())
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/js/'));
});

// nunjucks to html
gulp.task('nunjucks', function() {
 nunjucksRender.nunjucks.configure([projectName + '/nunjucks_templates/'],{ watch: false });

  // Gets .html and .nunjucks files in pages
  return gulp.src(projectName + '/nunjucks_pages/*.nunjucks')
  // Renders template with nunjucks
  .pipe(nunjucksRender({
      title:'Theft',
      moto:'GTA Cheats'
  }))
  .pipe(plumber())
  // output files in app folder
  .pipe(gulp.dest(dist))

});

// games to html
gulp.task('gameMake', function() {

 nunjucksRender.nunjucks.configure([projectName + '/nunjucks_templates/'],{ watch: false });

  // Gets .html and .nunjucks files in pages
  return gulp.src(projectName + '/game_pages/*.nunjucks')
  // Renders template with nunjucks
  .pipe(data(function() {
   return require('./theft/api/theftdb.json')
  }))
  .pipe(nunjucksRender({
      title:'Theft',
      moto:'GTA Cheats'
  }))
  .pipe(plumber())
  .pipe(htmlmin({collapseWhitespace: true}))
  // output files in app folder
  .pipe(gulp.dest(dist + '/games/'));

});

// copy paste content of public folder to dist
gulp.task('public', function() {
  gulp.src(projectName + '/public/*/*.**')
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/'));
});
gulp.task('publicBase', function() {
  gulp.src(projectName + '/public/*.**')
        .pipe(plumber())
        .pipe(gulp.dest(dist + '/'));
});

/* svg sprites */
/* type 'gulp svgstore' in console */
var path = require('path');

gulp.task('svgstore', function () {
    return gulp
        .src(projectName + '/svgAssets/*.svg')
        .pipe(svgmin(function (file) {
            var prefix = path.basename(file.relative, path.extname(file.relative));
            return {
                plugins: [{
                    cleanupIDs: {
                        prefix: prefix + '-',
                        minify: true
                    }
                }]
            }
        }))
        .pipe(rename({prefix: 'icon-'}))
        .pipe(svgstore())
        .pipe(gulp.dest(projectName + '/nunjucks_templates/partials/'));
});

/* Watch for changes */
/* Generic */
gulp.task('watch',function(){
	gulp.watch(projectName + '/scss/**/*.scss',['scssToCss']);
	gulp.watch(projectName + '/scripts/*.js',['jsCompress']);
	gulp.watch(projectName + '/nunjucks_pages/*.nunjucks',['nunjucks']);
	gulp.watch(projectName + '/nunjucks_templates/**/*.nunjucks',['nunjucks']);
	gulp.watch(projectName + '/game_pages/*.nunjucks',['gameMake']);
});

/* Default Gulp task */
/* type Gulp in console */

/* Local Testing */
gulp.task('default', ['scssToCss','jsCompress','browser-sync','nunjucks','gameMake','watch']);
gulp.task('openbrowser', ['scssToCss','jsCompress','svgstore','public','publicBase','browser-sync-open-browser','nunjucks','gameMake','watch']);

/* distribution version */
gulp.task('web', ['scssToCssWeb','jsCompressWeb','browser-sync','nunjucks','gameMake','watch']);

<|endoftext|>


<commit_before>// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      1.0.0
// @description  A userscript for convenient viewing SFcomic.
// @author       AntonioTsai
// @include      /^http[s]?\:\/\/comic.sfacg.com\/HTML\/.*\/$/
// @include      /^http[s]?\:\/\/manhua.sfacg.com\/mh\/.*\/$/
// @ include      /^http[s]?\:\/\/www.acg456.com\/HTML\/.*\/$/
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/**
 * picAy: The array store all image's url of the volume
 * hosts: The array store possible host
 * getHost(): Get the current host index
 */
(() => {
  const imgTable = document.querySelector('table tbody')
  const tempTr = document.createElement('tr')
  tempTr.appendChild(document.createElement('td'))

  // Remove original image & social media icon
  imgTable.querySelector('tr').remove()

  // Render all images
  picAy.map((pic) => {
    const imgTr = tempTr.cloneNode(true)
    const img = document.createElement('img')

    img.src = hosts[getHost()] + pic
    img.className = 'scalable'
    imgTr.querySelector('td').appendChild(img)
    imgTable.appendChild(imgTr)
  })

  // Add CSS style
  const customStyle = document.createElement('style')
  let styleSheet

  document.head.appendChild(customStyle)
  styleSheet = customStyle.sheet

  // Scale down image to fit screen size
  // Set max-width to a huge number to ensure img show as its original size
  styleSheet.insertRule(`img.scalable {
    max-width: 100vw;
    width: auto;
    -webkit-transition: max-width .5s 1s;
    transition: transition: max-width .5s 1s;
  }`)

  // Scale up to original size when hovering
  styleSheet.insertRule(`img.scalable:hover {
    max-width: 5000px;
    -webkit-transition: max-width .25s 0.5s;
    transition: max-width .25s 0.5s;
  }`)

  const topPagination = document.querySelector('.Reduction_top + .wrap > .page_turning')

  // Remove tips
  topPagination.lastChild.remove()

  //  Center top pagination
  styleSheet.insertRule(`.Reduction_top + .wrap > .page_turning
  {
    text-align: center !important;
  }`)

  // Remove unnecessary NextPage & PrePage button
  // Select the button on the top
  const topButtons = document.querySelectorAll('.Reduction_top + .wrap > .page_turning > :not(:nth-child(n+6)):not(:nth-child(-n+2))')
  topButtons.forEach((current) => {
    current.remove()
  })

  // Select the button at the bottom
  const bottomButtons = document.querySelectorAll('table + .wrap > .page_turning > :not(:nth-child(n+5)):not(:nth-child(-n+1))')
  bottomButtons.forEach((current) => {
    current.remove()
  })
})()
<commit_msg>Add include rule according to site change<commit_after>// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      1.0.0
// @description  A userscript for convenient viewing SFcomic.
// @author       AntonioTsai
// @include      /^http[s]?\:\/\/comic.sfacg.com\/HTML\/.*\/$/
// @include      /^http[s]?\:\/\/manhua.sfacg.com\/mh\/.*\/$/
// @include      /^http[s]?\:\/\/www.acg456.com\/HTML\/.*\/$/
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/**
 * picAy: The array store all image's url of the volume
 * hosts: The array store possible host
 * getHost(): Get the current host index
 */
(() => {
  const imgTable = document.querySelector('table tbody')
  const tempTr = document.createElement('tr')
  tempTr.appendChild(document.createElement('td'))

  // Remove original image & social media icon
  imgTable.querySelector('tr').remove()

  // Render all images
  picAy.map((pic) => {
    const imgTr = tempTr.cloneNode(true)
    const img = document.createElement('img')

    img.src = pic
    img.className = 'scalable'
    imgTr.querySelector('td').appendChild(img)
    imgTable.appendChild(imgTr)
  })

  // Add CSS style
  const customStyle = document.createElement('style')
  let styleSheet

  document.head.appendChild(customStyle)
  styleSheet = customStyle.sheet

  // Scale down image to fit screen size
  // Set max-width to a huge number to ensure img show as its original size
  styleSheet.insertRule(`img.scalable {
    max-width: 100vw;
    width: auto;
    -webkit-transition: max-width .5s 1s;
    transition: transition: max-width .5s 1s;
  }`)

  // Scale up to original size when hovering
  styleSheet.insertRule(`img.scalable:hover {
    max-width: 5000px;
    -webkit-transition: max-width .25s 0.5s;
    transition: max-width .25s 0.5s;
  }`)

  const topPagination = document.querySelector('.Reduction_top + .wrap > .page_turning')

  // Remove tips
  topPagination.lastChild.remove()

  //  Center top pagination
  styleSheet.insertRule(`.Reduction_top + .wrap > .page_turning
  {
    text-align: center !important;
  }`)

  // Remove unnecessary NextPage & PrePage button
  // Select the button on the top
  const topButtons = document.querySelectorAll('.Reduction_top + .wrap > .page_turning > :not(:nth-child(n+6)):not(:nth-child(-n+2))')
  topButtons.forEach((current) => {
    current.remove()
  })

  // Select the button at the bottom
  const bottomButtons = document.querySelectorAll('table + .wrap > .page_turning > :not(:nth-child(n+5)):not(:nth-child(-n+1))')
  bottomButtons.forEach((current) => {
    current.remove()
  })
})()
<|endoftext|>


<commit_before>/* MONGODB SCRIPTS */

//connect to host
mongo "mongodb://myasaworld-shard-00-00-zadym.mongodb.net:27017,myasaworld-shard-00-01-zadym.mongodb.net:27017,myasaworld-shard-00-02-zadym.mongodb.net:27017/test?replicaSet=myasaworld-shard-0" --authenticationDatabase admin --ssl --username <USERNAME> --password <PASSWORD>

//switch database
use asa

// check current db
db

// create collection
db.createCollection(“test”)

// insert document into test collection
db.test.insert(
{'name':'ADMIN','stress':'high'}
)

// check result of operation OR show collection
db.test.find().pretty()

// search regex
db.member.find({"name": /.*search_query.*/search_options})

<commit_msg>Update db.js<commit_after>/* MONGODB SCRIPTS */
// link for spring data queries : https://docs.spring.io/spring-data/data-mongo/docs/current/reference/html/#mongodb.repositories.queries

//connect to host
mongo "mongodb://myasaworld-shard-00-00-zadym.mongodb.net:27017,myasaworld-shard-00-01-zadym.mongodb.net:27017,myasaworld-shard-00-02-zadym.mongodb.net:27017/test?replicaSet=myasaworld-shard-0" --authenticationDatabase admin --ssl --username <USERNAME> --password <PASSWORD>

//switch database
use asa

// check current db
db

// create collection
db.createCollection(“test”)

// insert document into test collection
db.test.insert(
{'name':'ADMIN','stress':'high'}
)

// check result of operation OR show collection
db.test.find().pretty()

// search regex
db.member.find({"name": /.*search_query.*/search_options})

// count
count()
<|endoftext|>


<commit_before>Screenful.Navigator={
  start: function(){
    Screenful.createEnvelope();
    $("#envelope").html("

");
    $("#editbox").html("");
    $("#navbox").html("
<button class='iconOnly' id='butCritOpen'> </button><input id='searchbox' title='Ctrl + Shift + T'/><button id='butSearch' class='iconOnly mergeLeft noborder'> </buttton><button class='iconYes noborder' id='butCritRemove' style='display: none;'>"+Screenful.Loc.removeFilter+"</button>
");
    $("#navbox").append("
 ▼

");
    $("#searchbox").on("keydown", function(e){if(!e.altKey && !((e.ctrlKey || e.metaKey) && e.shiftKey)) e.stopPropagation()});
    $("#searchbox").on("keyup", function(event){
      if(event.which==27) $("#searchbox").val("");
      if(event.which==13) Screenful.Navigator.critGo(event);
    });
    $("#butSearch").on("click", Screenful.Navigator.critGo);
    $("#navbox").append("
0<button class='iconYes noborder' id='butReload'>"+Screenful.Loc.reload+"</button>
");
    if(!(Screenful.Navigator.critEditor && Screenful.Navigator.critHarvester)) $("#butCritOpen").remove();
    $("#butCritOpen").on("click", Screenful.Navigator.critOpen);
    $("#butReload").on("click", Screenful.Navigator.reload);
    $("#critbox").html("

<button class='iconYes' id='butCritCancel'>"+Screenful.Loc.cancel+"</button><button class='iconYes' id='butCritGo'>"+Screenful.Loc.filter+"</button>
");
    $("#critbox").on("keydown", function(e){e.stopPropagation(); e.preventDefault()});
    $("#butCritCancel").on("click", Screenful.Navigator.critCancel);
    $("#butCritGo").on("click", Screenful.Navigator.critGo);
    $("#butCritRemove").on("click", Screenful.Navigator.critRemove);
    if(Screenful.Navigator.modifiers && Screenful.Navigator.modifiers.length>0){
      $("#navbox").addClass("hasSearchModifiers");
      $("#listbox").addClass("hasSearchModifiers");
      $("#navbox .lineModifiers .clickable .current").html(Screenful.Navigator.modifiers[0].caption).data("value", Screenful.Navigator.modifiers[0].value);
      for(var i=0; i<Screenful.Navigator.modifiers.length; i++){
        var obj=Screenful.Navigator.modifiers[i];
        $("#navbox .lineModifiers .menu").append(""+obj.caption+"")
      }
      $("#navbox .lineModifiers .clickable").on("click", function(e){
        var $mymenu=$(e.delegateTarget).closest(".lineModifiers").find(".menu");
        $(".menu").not($mymenu).slideUp();
        $mymenu.hide().slideDown();
        e.stopPropagation();
      });
    }
    $(document).on("click", function(e){
      $(".menu").slideUp();
    });
    if(Screenful.Navigator.critEditor && Screenful.Navigator.critHarvester) {
      $("#navbox .lineModifiers").addClass("hasCrits");
      Screenful.Navigator.critEditor(document.getElementById("editor"));
      Screenful.Navigator.critTemplate=Screenful.Navigator.critHarvester(document.getElementById("editor"));
    }
    window.setTimeout(Screenful.Navigator.list, 1000);
    $(document).on("click", function(){
      if(window.frames["editframe"] && window.frames["editframe"].Xonomy) window.frames["editframe"].Xonomy.clickoff();
    });

    //keyboard nav:
    $(document).on("keydown", function(e){
      if(e.which==37 && e.altKey){ //arrow down key
        e.preventDefault();
        Screenful.Navigator.focusEntryList();
      }
      if(e.which==39 && e.altKey){ //arrow right key
        if(window.frames["editframe"].Screenful) {
          e.preventDefault();
          window.frames["editframe"].focus();
        }
      }
      //console.log(e.which, e.ctrlKey, e.metaKey, e.altKey, e.altGraphKey, e.shiftKey);
      if(e.which==84 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //T key
        e.preventDefault();
        e.stopImmediatePropagation();
        $("#searchbox").focus();
      }
      if(e.which==69 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //E key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butEdit:visible").click();
          window.frames["editframe"].$("#butView:visible").click();
          window.frames["editframe"].focus();
        }
      }
      if(e.which==83 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //S key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butSave:visible").click();
          window.frames["editframe"].focus();
        }
      }
      if(e.which==78 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //N key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butNew:visible").click();
          window.frames["editframe"].focus();
        }
      }
    });
  },

  lastFocusedEntryID: "",
  focusEntryList: function(){
    if(Screenful.Navigator.lastFocusedEntryID && $("#listbox .entry[data-id=\""+Screenful.Navigator.lastFocusedEntryID+"\"]").length>0)
      $("#listbox .entry[data-id=\""+Screenful.Navigator.lastFocusedEntryID+"\"]").focus();
    else
      $("#listbox .entry").first().focus();
  },

  list: function(event, howmany, noSFX){
    if(!howmany) howmany=Screenful.Navigator.stepSize;
    Screenful.Navigator.lastStepSize=howmany;
    Screenful.status(Screenful.Loc.listing, "wait"); //"getting list of entries"
    var url=Screenful.Navigator.listUrl;
    var criteria=null; if(Screenful.Navigator.critHarvester) criteria=Screenful.Navigator.critHarvester(document.getElementById("editor"));
    var searchtext=$.trim($("#searchbox").val());
    var modifier=$.trim($("#navbox .lineModifiers .current").data("value"));
    if(criteria!=Screenful.Navigator.critTemplate) {
      $("#butCritOpen").addClass("on");
      $("#butCritRemove").show();
    } else {
      $("#butCritOpen").removeClass("on");
      $("#butCritRemove").hide();
    }
    if(searchtext!="") $("#butCritRemove").show();
    $.ajax({url: url, dataType: "json", method: "POST", data: {criteria: criteria, searchtext: searchtext, modifier: modifier, howmany: howmany}}).done(function(data){
      if(!data.success) {
        Screenful.status(Screenful.Loc.listingFailed, "warn"); //"failed to get list of entries"
      } else {
        $("#countcaption").html(data.total);
        var $listbox=$("#listbox").html("");
        data.entries.forEach(function(entry){
          var $item=$("
"+entry.id+"
").appendTo($listbox);
          Screenful.Navigator.renderer($item.toArray()[0], entry, searchtext, modifier);
          $item.on("click", entry, Screenful.Navigator.openEntry);

          //entry menu:
          if(Screenful.Navigator.entryDeleteUrl){
            var $menuLink=$("···").appendTo($item);
            $menuLink.on("click", Screenful.Navigator.entryMenuLinkClick);
            var $menu=$("

").appendTo($item);
            var $menuItem=$("Del"+Screenful.Loc.delete+"").appendTo($menu);
            $menuItem.on("click", Screenful.Navigator.entryDelete);
          }

        });
        if(!noSFX) $listbox.hide().fadeIn();
        if(data.entries.length<data.total){
          $listbox.append("
<button class='iconYes' id='butMore'>"+Screenful.Loc.more+"</button>
");
          $("#butMore").on("click", Screenful.Navigator.more);
        }
        if(window.frames["editframe"] && window.frames["editframe"].Screenful && window.frames["editframe"].Screenful.Editor) {
          var currentEntryID=window.frames["editframe"].Screenful.Editor.entryID;
          Screenful.Navigator.setEntryAsCurrent(currentEntryID);
        }
        Screenful.status(Screenful.Loc.ready);
        Screenful.Navigator.focusEntryList();

        //keyboard nav:
        $("#listbox .entry").on("keydown", function(e){
          if(e.which==40){ //arrow down key
            e.preventDefault();
            if(e.ctrlKey||e.metaKey) $("#listbox").scrollTop($("#listbox").scrollTop()+60);
            else {
              $(e.delegateTarget).next().focus();
              Screenful.Navigator.lastFocusedEntryID=$("#listbox .entry:focus").attr("data-id");
            }
          }
          if(e.which==38){ //arrow up key
            e.preventDefault();
            if(e.ctrlKey||e.metaKey) $("#listbox").scrollTop($("#listbox").scrollTop()-60);
            else {
              $(e.delegateTarget).prev().focus();
              Screenful.Navigator.lastFocusedEntryID=$("#listbox .entry:focus").attr("data-id");
            }
          }
          if(e.which==13){ //Enter key
            e.preventDefault(); $(e.delegateTarget).click();
          }
          if(e.which==46){ //Delete key
            e.preventDefault();
            Screenful.Navigator.entryDelete(e);
          }
        });
        $("#listbox .entry").on("click", function(e){
          Screenful.Navigator.lastFocusedEntryID=$(e.delegateTarget).attr("data-id");
        });
      }
    });
  },
  lastStepSize: 0,
  more: function(event){
    Screenful.Navigator.list(event, Screenful.Navigator.lastStepSize+Screenful.Navigator.stepSize);
  },
  openEntry: function(event){
    var entry=event.data;
    if(window.frames["editframe"].Screenful) {
      window.frames["editframe"].Screenful.Editor.open(null, entry.id);
    }
  },
  setEntryAsCurrent: function(id){
    $("#listbox .entry").removeClass("current")
    $("div.entry[data-id=\""+id+"\"]").addClass("current");
  },

  previousCrit: null,
  critOpen: function(event){
    Screenful.Navigator.previousCrit=Screenful.Navigator.critHarvester(document.getElementById("editor")); //save previous criteria for later, in case the user cancels
    $("#curtain").show().one("click", Screenful.Navigator.critCancel);
    $("#critbox").show().focus();
  },
  critCancel: function(event){
    $("#critbox").hide();
    $("#curtain").hide();
    Screenful.Navigator.critEditor(document.getElementById("editor"), Screenful.Navigator.previousCrit); //restore previous criteria
  },
  critGo: function(event){
    $("#critbox").hide();
    $("#curtain").hide();
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  critRemove: function(event){
    if(Screenful.Navigator.critEditor) Screenful.Navigator.critEditor(document.getElementById("editor"));
    $("#searchbox").val("");
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  reload: function(event){
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  refresh: function(){
    Screenful.Navigator.list(null, Screenful.Navigator.lastStepSize, true);
  },
  setModifier: function(i){
    var obj=Screenful.Navigator.modifiers[i];
    $("#navbox .lineModifiers .clickable .current").html(obj.caption).data("value", obj.value);
    if($.trim($("#searchbox").val())!="") Screenful.Navigator.list();
  },

  entryMenuLinkClick: function(e){
    e.stopPropagation();
    var $menuLink=$(e.delegateTarget);
    var $entry=$menuLink.closest(".entry");
    var entryID=$entry.attr("data-id");
    var $menu=$entry.find(".menu");
    $("#listbox .menu").not($menu).hide();
    $(".menu").not($menu).slideUp();
    $menu.hide().slideDown();
    e.stopPropagation();
  },
  entryDelete: function(arg){ //arg = event object or entryID
    var enryID=arg; if(typeof(arg)=="object") {
      entryID=$(arg.delegateTarget).closest(".entry").attr("data-id");
      $(".menu").hide();
      arg.stopPropagation();
    }
    if(window.frames["editframe"].Screenful && window.frames["editframe"].Screenful.Editor && window.frames["editframe"].Screenful.Editor.entryID==entryID) {
      window.frames["editframe"].Screenful.Editor.delete();
    } else {
      if(confirm(Screenful.Loc.deleteConfirm)){ //"are you sure?"
        Screenful.status(Screenful.Loc.deleting, "wait"); //"deleting entry..."
        $.ajax({url: Screenful.Navigator.entryDeleteUrl, dataType: "json", method: "POST", data: {id: entryID}}).done(function(data){
          if(!data.success) {
            Screenful.status(Screenful.Loc.deletingFailed, "warn"); //"failed to delete entry"
          } else {
            Screenful.status(Screenful.Loc.ready);
            var $entry=$("div.entry[data-id=\""+entryID+"\"]");
            if($entry.length>0){
              var $next=$entry.next(".entry"); if($next.length==0) $next=$entry.prev(".entry"); Screenful.Navigator.lastFocusedEntryID=$next.attr("data-id");
              Screenful.Navigator.refresh();
            }
          }
      	});
      }
    }
  },
};
$(window).ready(Screenful.Navigator.start);
<commit_msg>fix typo (enry -> entry)<commit_after>Screenful.Navigator={
  start: function(){
    Screenful.createEnvelope();
    $("#envelope").html("

");
    $("#editbox").html("");
    $("#navbox").html("
<button class='iconOnly' id='butCritOpen'> </button><input id='searchbox' title='Ctrl + Shift + T'/><button id='butSearch' class='iconOnly mergeLeft noborder'> </buttton><button class='iconYes noborder' id='butCritRemove' style='display: none;'>"+Screenful.Loc.removeFilter+"</button>
");
    $("#navbox").append("
 ▼

");
    $("#searchbox").on("keydown", function(e){if(!e.altKey && !((e.ctrlKey || e.metaKey) && e.shiftKey)) e.stopPropagation()});
    $("#searchbox").on("keyup", function(event){
      if(event.which==27) $("#searchbox").val("");
      if(event.which==13) Screenful.Navigator.critGo(event);
    });
    $("#butSearch").on("click", Screenful.Navigator.critGo);
    $("#navbox").append("
0<button class='iconYes noborder' id='butReload'>"+Screenful.Loc.reload+"</button>
");
    if(!(Screenful.Navigator.critEditor && Screenful.Navigator.critHarvester)) $("#butCritOpen").remove();
    $("#butCritOpen").on("click", Screenful.Navigator.critOpen);
    $("#butReload").on("click", Screenful.Navigator.reload);
    $("#critbox").html("

<button class='iconYes' id='butCritCancel'>"+Screenful.Loc.cancel+"</button><button class='iconYes' id='butCritGo'>"+Screenful.Loc.filter+"</button>
");
    $("#critbox").on("keydown", function(e){e.stopPropagation(); e.preventDefault()});
    $("#butCritCancel").on("click", Screenful.Navigator.critCancel);
    $("#butCritGo").on("click", Screenful.Navigator.critGo);
    $("#butCritRemove").on("click", Screenful.Navigator.critRemove);
    if(Screenful.Navigator.modifiers && Screenful.Navigator.modifiers.length>0){
      $("#navbox").addClass("hasSearchModifiers");
      $("#listbox").addClass("hasSearchModifiers");
      $("#navbox .lineModifiers .clickable .current").html(Screenful.Navigator.modifiers[0].caption).data("value", Screenful.Navigator.modifiers[0].value);
      for(var i=0; i<Screenful.Navigator.modifiers.length; i++){
        var obj=Screenful.Navigator.modifiers[i];
        $("#navbox .lineModifiers .menu").append(""+obj.caption+"")
      }
      $("#navbox .lineModifiers .clickable").on("click", function(e){
        var $mymenu=$(e.delegateTarget).closest(".lineModifiers").find(".menu");
        $(".menu").not($mymenu).slideUp();
        $mymenu.hide().slideDown();
        e.stopPropagation();
      });
    }
    $(document).on("click", function(e){
      $(".menu").slideUp();
    });
    if(Screenful.Navigator.critEditor && Screenful.Navigator.critHarvester) {
      $("#navbox .lineModifiers").addClass("hasCrits");
      Screenful.Navigator.critEditor(document.getElementById("editor"));
      Screenful.Navigator.critTemplate=Screenful.Navigator.critHarvester(document.getElementById("editor"));
    }
    window.setTimeout(Screenful.Navigator.list, 1000);
    $(document).on("click", function(){
      if(window.frames["editframe"] && window.frames["editframe"].Xonomy) window.frames["editframe"].Xonomy.clickoff();
    });

    //keyboard nav:
    $(document).on("keydown", function(e){
      if(e.which==37 && e.altKey){ //arrow down key
        e.preventDefault();
        Screenful.Navigator.focusEntryList();
      }
      if(e.which==39 && e.altKey){ //arrow right key
        if(window.frames["editframe"].Screenful) {
          e.preventDefault();
          window.frames["editframe"].focus();
        }
      }
      //console.log(e.which, e.ctrlKey, e.metaKey, e.altKey, e.altGraphKey, e.shiftKey);
      if(e.which==84 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //T key
        e.preventDefault();
        e.stopImmediatePropagation();
        $("#searchbox").focus();
      }
      if(e.which==69 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //E key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butEdit:visible").click();
          window.frames["editframe"].$("#butView:visible").click();
          window.frames["editframe"].focus();
        }
      }
      if(e.which==83 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //S key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butSave:visible").click();
          window.frames["editframe"].focus();
        }
      }
      if(e.which==78 && (e.ctrlKey||e.metaKey) && e.shiftKey){ //N key
        if(window.frames["editframe"].Screenful){
          e.preventDefault();
          e.stopImmediatePropagation();
          window.frames["editframe"].$("#butNew:visible").click();
          window.frames["editframe"].focus();
        }
      }
    });
  },

  lastFocusedEntryID: "",
  focusEntryList: function(){
    if(Screenful.Navigator.lastFocusedEntryID && $("#listbox .entry[data-id=\""+Screenful.Navigator.lastFocusedEntryID+"\"]").length>0)
      $("#listbox .entry[data-id=\""+Screenful.Navigator.lastFocusedEntryID+"\"]").focus();
    else
      $("#listbox .entry").first().focus();
  },

  list: function(event, howmany, noSFX){
    if(!howmany) howmany=Screenful.Navigator.stepSize;
    Screenful.Navigator.lastStepSize=howmany;
    Screenful.status(Screenful.Loc.listing, "wait"); //"getting list of entries"
    var url=Screenful.Navigator.listUrl;
    var criteria=null; if(Screenful.Navigator.critHarvester) criteria=Screenful.Navigator.critHarvester(document.getElementById("editor"));
    var searchtext=$.trim($("#searchbox").val());
    var modifier=$.trim($("#navbox .lineModifiers .current").data("value"));
    if(criteria!=Screenful.Navigator.critTemplate) {
      $("#butCritOpen").addClass("on");
      $("#butCritRemove").show();
    } else {
      $("#butCritOpen").removeClass("on");
      $("#butCritRemove").hide();
    }
    if(searchtext!="") $("#butCritRemove").show();
    $.ajax({url: url, dataType: "json", method: "POST", data: {criteria: criteria, searchtext: searchtext, modifier: modifier, howmany: howmany}}).done(function(data){
      if(!data.success) {
        Screenful.status(Screenful.Loc.listingFailed, "warn"); //"failed to get list of entries"
      } else {
        $("#countcaption").html(data.total);
        var $listbox=$("#listbox").html("");
        data.entries.forEach(function(entry){
          var $item=$("
"+entry.id+"
").appendTo($listbox);
          Screenful.Navigator.renderer($item.toArray()[0], entry, searchtext, modifier);
          $item.on("click", entry, Screenful.Navigator.openEntry);

          //entry menu:
          if(Screenful.Navigator.entryDeleteUrl){
            var $menuLink=$("···").appendTo($item);
            $menuLink.on("click", Screenful.Navigator.entryMenuLinkClick);
            var $menu=$("

").appendTo($item);
            var $menuItem=$("Del"+Screenful.Loc.delete+"").appendTo($menu);
            $menuItem.on("click", Screenful.Navigator.entryDelete);
          }

        });
        if(!noSFX) $listbox.hide().fadeIn();
        if(data.entries.length<data.total){
          $listbox.append("
<button class='iconYes' id='butMore'>"+Screenful.Loc.more+"</button>
");
          $("#butMore").on("click", Screenful.Navigator.more);
        }
        if(window.frames["editframe"] && window.frames["editframe"].Screenful && window.frames["editframe"].Screenful.Editor) {
          var currentEntryID=window.frames["editframe"].Screenful.Editor.entryID;
          Screenful.Navigator.setEntryAsCurrent(currentEntryID);
        }
        Screenful.status(Screenful.Loc.ready);
        Screenful.Navigator.focusEntryList();

        //keyboard nav:
        $("#listbox .entry").on("keydown", function(e){
          if(e.which==40){ //arrow down key
            e.preventDefault();
            if(e.ctrlKey||e.metaKey) $("#listbox").scrollTop($("#listbox").scrollTop()+60);
            else {
              $(e.delegateTarget).next().focus();
              Screenful.Navigator.lastFocusedEntryID=$("#listbox .entry:focus").attr("data-id");
            }
          }
          if(e.which==38){ //arrow up key
            e.preventDefault();
            if(e.ctrlKey||e.metaKey) $("#listbox").scrollTop($("#listbox").scrollTop()-60);
            else {
              $(e.delegateTarget).prev().focus();
              Screenful.Navigator.lastFocusedEntryID=$("#listbox .entry:focus").attr("data-id");
            }
          }
          if(e.which==13){ //Enter key
            e.preventDefault(); $(e.delegateTarget).click();
          }
          if(e.which==46){ //Delete key
            e.preventDefault();
            Screenful.Navigator.entryDelete(e);
          }
        });
        $("#listbox .entry").on("click", function(e){
          Screenful.Navigator.lastFocusedEntryID=$(e.delegateTarget).attr("data-id");
        });
      }
    });
  },
  lastStepSize: 0,
  more: function(event){
    Screenful.Navigator.list(event, Screenful.Navigator.lastStepSize+Screenful.Navigator.stepSize);
  },
  openEntry: function(event){
    var entry=event.data;
    if(window.frames["editframe"].Screenful) {
      window.frames["editframe"].Screenful.Editor.open(null, entry.id);
    }
  },
  setEntryAsCurrent: function(id){
    $("#listbox .entry").removeClass("current")
    $("div.entry[data-id=\""+id+"\"]").addClass("current");
  },

  previousCrit: null,
  critOpen: function(event){
    Screenful.Navigator.previousCrit=Screenful.Navigator.critHarvester(document.getElementById("editor")); //save previous criteria for later, in case the user cancels
    $("#curtain").show().one("click", Screenful.Navigator.critCancel);
    $("#critbox").show().focus();
  },
  critCancel: function(event){
    $("#critbox").hide();
    $("#curtain").hide();
    Screenful.Navigator.critEditor(document.getElementById("editor"), Screenful.Navigator.previousCrit); //restore previous criteria
  },
  critGo: function(event){
    $("#critbox").hide();
    $("#curtain").hide();
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  critRemove: function(event){
    if(Screenful.Navigator.critEditor) Screenful.Navigator.critEditor(document.getElementById("editor"));
    $("#searchbox").val("");
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  reload: function(event){
    $("#listbox").scrollTop(0);
    Screenful.Navigator.list();
  },
  refresh: function(){
    Screenful.Navigator.list(null, Screenful.Navigator.lastStepSize, true);
  },
  setModifier: function(i){
    var obj=Screenful.Navigator.modifiers[i];
    $("#navbox .lineModifiers .clickable .current").html(obj.caption).data("value", obj.value);
    if($.trim($("#searchbox").val())!="") Screenful.Navigator.list();
  },

  entryMenuLinkClick: function(e){
    e.stopPropagation();
    var $menuLink=$(e.delegateTarget);
    var $entry=$menuLink.closest(".entry");
    var entryID=$entry.attr("data-id");
    var $menu=$entry.find(".menu");
    $("#listbox .menu").not($menu).hide();
    $(".menu").not($menu).slideUp();
    $menu.hide().slideDown();
    e.stopPropagation();
  },
  entryDelete: function(arg){ //arg = event object or entryID
    var entryID=arg; if(typeof(arg)=="object") {
      entryID=$(arg.delegateTarget).closest(".entry").attr("data-id");
      $(".menu").hide();
      arg.stopPropagation();
    }
    if(window.frames["editframe"].Screenful && window.frames["editframe"].Screenful.Editor && window.frames["editframe"].Screenful.Editor.entryID==entryID) {
      window.frames["editframe"].Screenful.Editor.delete();
    } else {
      if(confirm(Screenful.Loc.deleteConfirm)){ //"are you sure?"
        Screenful.status(Screenful.Loc.deleting, "wait"); //"deleting entry..."
        $.ajax({url: Screenful.Navigator.entryDeleteUrl, dataType: "json", method: "POST", data: {id: entryID}}).done(function(data){
          if(!data.success) {
            Screenful.status(Screenful.Loc.deletingFailed, "warn"); //"failed to delete entry"
          } else {
            Screenful.status(Screenful.Loc.ready);
            var $entry=$("div.entry[data-id=\""+entryID+"\"]");
            if($entry.length>0){
              var $next=$entry.next(".entry"); if($next.length==0) $next=$entry.prev(".entry"); Screenful.Navigator.lastFocusedEntryID=$next.attr("data-id");
              Screenful.Navigator.refresh();
            }
          }
      	});
      }
    }
  },
};
$(window).ready(Screenful.Navigator.start);
<|endoftext|>


<commit_before>/**
 * Created by Oakley Hall on 6/16/15.
 */
'use strict';

var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var babel = require('gulp-babel');
var source = require('vinyl-source-stream');
var del = require('del');

gulp.task('build', ['clean', 'app', 'styles']);

gulp.task('clean', function (cb) {
  del([ 'dist/bundle.js'], cb);
});

gulp.task('templates', function () {
  return gulp.src('src/styles/**/*.*')
  .pipe(gulp.dest('dist'));
});

gulp.task('styles', function () {
  return gulp.src('src/styles/**/*.*')
  .pipe(gulp.dest('dist'));
});

gulp.task('lib', function () {
  return gulp.src('src/**/*.jsx')
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

gulp.task('app', function () {
  browserify({
    entries: 'src/index.jsx',
    extensions: ['.jsx'],
    debug: true
  })
  .transform(babelify)
  .bundle()
  .pipe(source('bundle.js'))
  .pipe(gulp.dest('dist'));
});

gulp.task('watch', ['build'], function() {
  gulp.watch('src/**/*.*', ['build']);
});

gulp.task('default', ['watch']);
<commit_msg>template build<commit_after>/**
 * Created by Oakley Hall on 6/16/15.
 */
'use strict';

var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var babel = require('gulp-babel');
var source = require('vinyl-source-stream');
var del = require('del');

gulp.task('build', ['clean', 'app', 'templates']);

gulp.task('clean', function (cb) {
  del([ 'dist/bundle.js'], cb);
});

gulp.task('templates', function () {
  return gulp.src('templates/*.*')
  .pipe(gulp.dest('dist'));
});

gulp.task('styles', function () {
  return gulp.src('src/styles/**/*.*')
  .pipe(gulp.dest('dist'));
});

gulp.task('lib', function () {
  return gulp.src('src/**/*.jsx')
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

gulp.task('app', function () {
  browserify({
    entries: 'src/index.jsx',
    extensions: ['.jsx'],
    debug: true
  })
  .transform(babelify)
  .bundle()
  .pipe(source('bundle.js'))
  .pipe(gulp.dest('dist'));
});

gulp.task('watch', ['build'], function() {
  gulp.watch('src/**/*.*', ['build']);
});

gulp.task('default', ['watch']);
<|endoftext|>


<commit_before>// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      1.1.2
// @description  A userscript for convenient viewing SFcomic.
// @author       AntonioTsai
// @include      /^http[s]?\:\/\/comic.sfacg.com\/HTML\/.*\/$/
// @include      /^http[s]?\:\/\/manhua.sfacg.com\/mh\/.*\/$/
// @include      /^http[s]?\:\/\/www.acg456.com\/HTML\/.*\/$/
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/* global picAy hosts getHost */
/**
 * {Array} picAy - Array of img urls of current volume
 * {Array} hosts - Array of possible host
 * {Function} getHost - Return the index of selected host in string type
 */
window.onload = _ => {
  (_ => {
    const imgTable = document.querySelector('table tbody')
    const tempTr = document.createElement('tr')
    tempTr.appendChild(document.createElement('td'))

    let host = ''
    if (typeof hosts !== 'undefined' && Array.isArray(hosts) && typeof getHost === 'function') {
      host = hosts[parseInt(getHost())]
    }

    // Remove original image & social media icon
    imgTable.querySelector('tr').remove()

    // Render all images
    // picAy - global array defined by site
    picAy.map((pic) => {
      const imgTr = tempTr.cloneNode(true)
      const img = document.createElement('img')

      img.src = host + pic
      img.className = 'scalable'
      imgTr.querySelector('td').appendChild(img)
      imgTable.appendChild(imgTr)
    })

    // Add CSS style
    let link = document.createElement('link')
    const cssFileUrl = 'https://antoniotsai.github.io/SFcomic-Viewer/files/css/style.css'
    link.setAttribute('rel', 'stylesheet')
    link.setAttribute('type', 'text/css')
    link.setAttribute('href', cssFileUrl)
    document.head.appendChild(link)

    const topPagination = document.querySelector('.Reduction_top + .wrap > .page_turning')

    // Remove tips
    topPagination.lastChild.remove()

    // Remove unnecessary NextPage & PrePage button
    // Select the button on the top
    const topButtons = topPagination.querySelectorAll(':not(:nth-child(n+6)):not(:nth-child(-n+2))')
    topButtons.forEach((current) => {
      current.remove()
    })

    // Select the button at the bottom
    const bottomButtons = document.querySelectorAll('table + .wrap > .page_turning > :not(:nth-child(n+5)):not(:nth-child(-n+1))')
    bottomButtons.forEach((current) => {
      current.remove()
    })
  })()
}
<commit_msg>Bump version number<commit_after>// ==UserScript==
// @name         SFcomic Viewer
// @namespace
// @version      1.1.4
// @description  A userscript for convenient viewing SFcomic.
// @author       AntonioTsai
// @include      /^http[s]?\:\/\/comic.sfacg.com\/HTML\/.*\/$/
// @include      /^http[s]?\:\/\/manhua.sfacg.com\/mh\/.*\/$/
// @include      /^http[s]?\:\/\/www.acg456.com\/HTML\/.*\/$/
// @grant        none
// @downloadURL  https://github.com/AntonioTsai/SFcomic-Viewer/raw/master/SFcomicViewer.user.js
// ==/UserScript==

/* global picAy hosts getHost */
/**
 * {Array} picAy - Array of img urls of current volume
 * {Array} hosts - Array of possible host
 * {Function} getHost - Return the index of selected host in string type
 */
window.onload = _ => {
  (_ => {
    const imgTable = document.querySelector('table tbody')
    const tempTr = document.createElement('tr')
    tempTr.appendChild(document.createElement('td'))

    let host = ''
    if (typeof hosts !== 'undefined' && Array.isArray(hosts) && typeof getHost === 'function') {
      host = hosts[parseInt(getHost())]
    }

    // Remove original image & social media icon
    imgTable.querySelector('tr').remove()

    // Render all images
    // picAy - global array defined by site
    picAy.map((pic) => {
      const imgTr = tempTr.cloneNode(true)
      const img = document.createElement('img')

      img.src = host + pic
      img.className = 'scalable'
      imgTr.querySelector('td').appendChild(img)
      imgTable.appendChild(imgTr)
    })

    // Add CSS style
    let link = document.createElement('link')
    const cssFileUrl = 'https://antoniotsai.github.io/SFcomic-Viewer/files/css/style.css'
    link.setAttribute('rel', 'stylesheet')
    link.setAttribute('type', 'text/css')
    link.setAttribute('href', cssFileUrl)
    document.head.appendChild(link)

    const topPagination = document.querySelector('.Reduction_top + .wrap > .page_turning')

    // Remove tips
    topPagination.lastChild.remove()

    // Remove unnecessary NextPage & PrePage button
    // Select the button on the top
    const topButtons = topPagination.querySelectorAll(':not(:nth-child(n+6)):not(:nth-child(-n+2))')
    topButtons.forEach((current) => {
      current.remove()
    })

    // Select the button at the bottom
    const bottomButtons = document.querySelectorAll('table + .wrap > .page_turning > :not(:nth-child(n+5)):not(:nth-child(-n+1))')
    bottomButtons.forEach((current) => {
      current.remove()
    })
  })()
}
<|endoftext|>


<commit_before>"use strict";

(function(){

  /*
   * So the structure is designed as follows:
   *
   * TodoItemController
   *   Controls a single item for the todo item. Handles the edit mode for
   *   a single todo. Handles showing and hiding the todo.
   * TodosController
   *   Controls a bunch of a TodoItemControllers. Has pagination, filtering,
   *   and creating new todos.
   * SingleTodoController
   *   Controls a single TodoItemController. Has commenting. Otherwise does
   *   not do much.
   */

  var module = angular.module("projecto");

  var toggleTodo = function(todo, force, noanimation) {
    // TODO: All of this needs to be moved into a directive.
    var bodyElement = $("#todo-" + todo.key);
    if (bodyElement.css("display") === "none") {
      if (force != "close") {
        if (noanimation)
          bodyElement.show();
        else
          bodyElement.slideDown();
      }
    } else {
      if (force != "open") {
        if (noanimation)
          bodyElement.hide();
        else
          bodyElement.slideUp();
      }
    }
  };

  var extractTags = function(tagstr) {
    if ($.type(tagstr) === "array")
      return tagstr;

    var tags = tagstr.split(",");
    for (var i=0; i<tags.length; i++) {
      tags[i] = $.trim(tags[i], " ");
      if (!tags[i]) {
        tags.splice(i, 1);
        i--;
      }
    }
    return tags;
  };

  module.controller("TodoItemController", ["$scope", "$window", "$timeout", "$filter", "$location", "toast", "Todos", function($scope, $window, $timeout, $filter, $location, toast, Todos) {
    $scope.todoDraft = null;
    $scope.displayed = false;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    $scope.toggleTodo = function(todo, event) {
      event.preventDefault();
      event.stopPropagation();
      toggleTodo(todo);
    };

    $scope.markDone = function(todo) {
      var req = todo.done();
      var error = function(data, status) {
        toast.error("Failed to mark done", status);
      };
      req.then(undefined, error);
    };

    $scope.editTodo = function(todo, noanimation) {
      if ($scope.todoDraft) {
        $scope.cancelEdit(todo.key);
      } else {
        toggleTodo(todo, "open", noanimation);
        $scope.todoDraft = new Todos.TodoItem(todo.key, todo.project, angular.copy(todo.data), todo.archived);
        if (todo.data.due)
          $scope.todoDraft.data.due = $filter("absoluteTime")(todo.data.due);
        $scope.$emit("enterEdit", todo.key, $scope.todoDraft);
      }
    };

    $scope.archiveTodo = function(todo) {
      if ($scope.currentProject) {
        toast.info("Archiving...");
        var req = todo.archive();
        var success = function() {
          toast.close();
          $scope.$emit("archived", todo.key);
        };

        var error = function(data, status) {
          toast.error("Failed to archive todo", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.deleteTodo = function(todo) {
      if (!$window.confirm("Are you sure you want to delete this todo?"))
        return;

      if ($scope.currentProject) {
        toast.info("Deleting...");
        var req = todo.delete();
        var success = function() {
          toast.close();
          $scope.$emit("deleted", todo.key);
        };

        var error = function(data, status) {
          toast.error("Failed to delete todo", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.saveTodo = function(todo, event) {
      if (!$scope.todoDraft) {
        toast.wtf("$scope.todoDraft does not exist while trying to save todo? Wat.");
        return;
      }

      if ($scope.currentProject) {
        if ($scope.todoDraft.data.tags)
          $scope.todoDraft.data.tags = extractTags($scope.todoDraft.data.tags);

        toast.info("Saving...");
        var req = $scope.todoDraft.save();
        var success = function(data) {
          $scope.$emit("saved", data);
          $scope.cancelEdit($scope.todoDraft.key, true);
          toast.success("Saved");
          toggleTodo(data, "open");
        };

        var error = function(data, status) {
          toast.error("Failed to save", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.cancelEdit = function(todoKey, justDoIt) { // Nike.
      if (justDoIt || $window.confirm("Are you sure you want to cancel? You will lose all changes!")) {
        $scope.$emit("exitEdit", $scope.todoDraft.key);
        $scope.todoDraft = null;
      }
    };

    // restores the todos that's currently being edited.
    $timeout(function() {
      if ($scope.currently_editing && $scope.currently_editing.indexOf($scope.todo.key) > -1) {
        $scope.editTodo($scope.current_draft_objects[$scope.todo.key], true);
      }
    }, 0);
  }]);

  module.controller("TodosController", ["$scope", "$location", "$window", "toast", "title", "Todos", "ProjectsService", function($scope, $location, $window, toast, title, Todos, ProjectsService) {
    $scope.newtodo = null;
    $scope.todolist = null;
    $scope.todolist_for_template = null;
    $scope.all_expanded = false;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    var regenerate_list_for_template = function() {
      $scope.todolist_for_template = $scope.todolist.todos.values();
    };

    $scope.currently_editing = [];
    // This stores a reference to the object for restoration of the draft
    // when we do some sort of operations on page.
    $scope.current_draft_objects = {};
    $scope.$on("enterEdit", function(e, todo_key, todo_draft) {
      if ($scope.currently_editing.indexOf(todo_key) === -1) {
        $scope.currently_editing.push(todo_key);
        $scope.current_draft_objects[todo_key] = todo_draft;
      }
    });

    var remove_from_currently_editing = function(todo_key) {
      var j = $scope.currently_editing.indexOf(todo_key);
      if (j > -1) {
        $scope.currently_editing.splice(j, 1);
        delete $scope.current_draft_objects[todo_key];
      }
    };

    $scope.$on("exitEdit", function(e, todo_key) {
      remove_from_currently_editing(todo_key);
    });

    var removed = function(e, todo_key) {
      $scope.todolist.todos.remove(todo_key);
      regenerate_list_for_template();
      $scope.todolist.totalTodos--;
      remove_from_currently_editing(todo_key);
    };

    $scope.$on("deleted", removed);
    $scope.$on("archived", removed);

    var add_to_tags_on_save = function(tags) {
      // WARNING: O(n^2) algorithm at least!
      // TODO: sort it, and then insert. O(nlogn) instead. Or when the list
      // is created it could be maintained in order O(nlogn) creation with
      // O(logn) insertion here.
      if (!tags)
        return;

      for (var i=0; i<tags.length; i++) {
        if ($scope.todolist.tags.indexOf(tags[i]) === -1) {
          // This line may push it to O(n^3)
          $scope.todolist.tags.unshift(tags[i]);
          $scope.todolist.toggleFilterTag(tags[i]);
        }
      }
    };

    $scope.$on("saved", function(e, newTodo) {
      var archived = false;
      if (newTodo.archived) {
        archived = newTodo.archived;
        delete newTodo.archived;
      }

      $scope.todolist.todos.put(newTodo.key, new Todos.TodoItem(newTodo.key, $scope.currentProject, newTodo, archived));
      regenerate_list_for_template();
      remove_from_currently_editing(newTodo.key);

      add_to_tags_on_save(newTodo.tags);
    });

    $scope.expand_todos = function() {
      regenerate_list_for_template();
      var list = $scope.todolist_for_template;
      for (var i=0, l=list.length; i<l; i++) {
        toggleTodo(list[i], "open");
      }
      $scope.all_expanded = true;
    };

    $scope.collapse_todos = function() {
      regenerate_list_for_template();
      var list = $scope.todolist_for_template;
      for (var i=0, l=list.length; i<l; i++) {
        toggleTodo(list[i], "close");
      }
      $scope.all_expanded = false;
    };

    $scope.new_todo = function() {
      $scope.newtodo = new Todos.TodoItem(undefined, $scope.currentProject, undefined, $scope.is_archived);
      $("#todos-new-todo").slideDown();
    };

    $scope.cancel_new_todo = function(force) {
      if ($.isEmptyObject($scope.newtodo.data) || force ||
          $window.confirm("Are you sure you want to cancel?")) {
        $scope.newtodo = null;
        $("#todos-new-todo").slideUp();
      }
    };

    $scope.create_todo = function() {
      var invalid_messages = $scope.newtodo.validate(true);
      if (!invalid_messages["invalid"]) {
        if ($scope.newtodo.data.tags)
          $scope.newtodo.data.tags = extractTags($scope.newtodo.data.tags);

        var req = $scope.newtodo.save();
        var success = function(data) {
          $scope.todolist.todos.prepend($scope.newtodo.key, $scope.newtodo);
          regenerate_list_for_template();
          add_to_tags_on_save($scope.newtodo.data.tags);
          $scope.cancel_new_todo(true);
        };

        var error = function(data, status) {
          toast.error("Failed to post", xhr.status);
        };
        req.then(success, error);
      } else {
        // TODO: Need a better way to display these messages in the future.
        toast.warn(invalid_messages["title"]);
      }
    };

    $scope.clear_done = function(todo) {
      var req = $scope.todolist.clearDone();
      var success = function() {
        regenerate_list_for_template();
      };
      var error = function(data, status) {
        toast.error("Failed to clear done", status);
      }
      req.then(success, error);
    };

    $scope.update = function(initial) {
      toast.info("Updating...");
      var req = $scope.todolist.fetch(initial);

      req.then(
        function(data) {
          regenerate_list_for_template();
          toast.close();
        },
        function(data, status) {
          toast.error("Failed to update todos", status);
        }
      );
    };

    $scope.toggle_filter_tag = function(tag) {
      $scope.todolist.toggleFilterTag(tag);
      $scope.update();
    };

    $scope.toggle_show_done = function() {
      $scope.todolist.showdone = !$scope.todolist.showdone;
      $scope.update();
    };

    $scope.toggle_show_notdone = function() {
      $scope.todolist.shownotdone = !$scope.todolist.shownotdone;
      $scope.update();
    };

    $scope.goto = function(page) {
      $scope.todolist.gotopage(page);
    };

    $scope.currentProject = null;
    ProjectsService.getCurrentProject().done(function(currentProject){
      if (currentProject){
        $scope.currentProject = currentProject;
        $scope.todolist = new Todos.TodoList($scope.currentProject, {archived: $scope.is_archived});
        title("Todos", $scope.currentProject);
        $scope.update(true);
        $scope.$$phase || $scope.$apply();
      } else {
        window.notLoaded();
      }
    });
  }]);

  module.controller("SingleTodoController", ["$scope", "$route", "$location", "toast", "title", "Todos", "ProjectsService", function($scope, $route, $location, toast, title, Todos, ProjectsService) {
    $scope.currentProject = null;
    $scope.todo = null;
    $scope.hideCommentLink = true;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    var removed = function(e, todo_key) {
      $location.path("/projects/" + $scope.currentProject.key + "/todos");
      $location.replace();
    };
    $scope.$on("deleted", removed);
    $scope.$on("archived", removed);

    var refresh_comments = function() {
      $scope.comments = $scope.todo.data.children;
      $scope.commentsParent = $scope.todo;
    };

    $scope.$on("saved", function(e, new_todo) {
      var archived = false;
      if (new_todo.archived) {
        archived = new_todo.archived;
        delete new_todo.archived;
      }

      $scope.todo = new Todos.TodoItem(new_todo.key, $scope.currentProject, new_todo, archived);
      refresh_comments();
    });

    $scope.update = function() {
      $scope.todo = new Todos.TodoItem($route.current.params.todoId, $scope.currentProject, undefined, $scope.is_archived);
      var req = $scope.todo.refresh();
      var success = function() {
        toast.loaded();
        refresh_comments();
        toggleTodo($scope.todo);
      };
      var error = function(data, status) {
        toast.error("Failed to load todos", status);
      };

      req.then(success, error);
    };

    ProjectsService.getCurrentProject().done(function(currentProject) {
      $scope.currentProject = currentProject;
      $scope.update();
      $scope.$$phase || $scope.$apply();
    }).fail(function(xhr) {
      toast.error("Failed to get project info", xhr.status);
    });
  }]);
})();
<commit_msg>Disable animations in single todo view<commit_after>"use strict";

(function(){

  /*
   * So the structure is designed as follows:
   *
   * TodoItemController
   *   Controls a single item for the todo item. Handles the edit mode for
   *   a single todo. Handles showing and hiding the todo.
   * TodosController
   *   Controls a bunch of a TodoItemControllers. Has pagination, filtering,
   *   and creating new todos.
   * SingleTodoController
   *   Controls a single TodoItemController. Has commenting. Otherwise does
   *   not do much.
   */

  var module = angular.module("projecto");

  var toggleTodo = function(todo, force, noanimation) {
    // TODO: All of this needs to be moved into a directive.
    var bodyElement = $("#todo-" + todo.key);
    if (bodyElement.css("display") === "none") {
      if (force != "close") {
        if (noanimation)
          bodyElement.show();
        else
          bodyElement.slideDown();
      }
    } else {
      if (force != "open") {
        if (noanimation)
          bodyElement.hide();
        else
          bodyElement.slideUp();
      }
    }
  };

  var extractTags = function(tagstr) {
    if ($.type(tagstr) === "array")
      return tagstr;

    var tags = tagstr.split(",");
    for (var i=0; i<tags.length; i++) {
      tags[i] = $.trim(tags[i], " ");
      if (!tags[i]) {
        tags.splice(i, 1);
        i--;
      }
    }
    return tags;
  };

  module.controller("TodoItemController", ["$scope", "$window", "$timeout", "$filter", "$location", "toast", "Todos", function($scope, $window, $timeout, $filter, $location, toast, Todos) {
    $scope.todoDraft = null;
    $scope.displayed = false;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    $scope.toggleTodo = function(todo, event) {
      event.preventDefault();
      event.stopPropagation();
      toggleTodo(todo);
    };

    $scope.markDone = function(todo) {
      var req = todo.done();
      var error = function(data, status) {
        toast.error("Failed to mark done", status);
      };
      req.then(undefined, error);
    };

    $scope.editTodo = function(todo, noanimation) {
      if ($scope.todoDraft) {
        $scope.cancelEdit(todo.key);
      } else {
        toggleTodo(todo, "open", noanimation);
        $scope.todoDraft = new Todos.TodoItem(todo.key, todo.project, angular.copy(todo.data), todo.archived);
        if (todo.data.due)
          $scope.todoDraft.data.due = $filter("absoluteTime")(todo.data.due);
        $scope.$emit("enterEdit", todo.key, $scope.todoDraft);
      }
    };

    $scope.archiveTodo = function(todo) {
      if ($scope.currentProject) {
        toast.info("Archiving...");
        var req = todo.archive();
        var success = function() {
          toast.close();
          $scope.$emit("archived", todo.key);
        };

        var error = function(data, status) {
          toast.error("Failed to archive todo", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.deleteTodo = function(todo) {
      if (!$window.confirm("Are you sure you want to delete this todo?"))
        return;

      if ($scope.currentProject) {
        toast.info("Deleting...");
        var req = todo.delete();
        var success = function() {
          toast.close();
          $scope.$emit("deleted", todo.key);
        };

        var error = function(data, status) {
          toast.error("Failed to delete todo", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.saveTodo = function(todo, event) {
      if (!$scope.todoDraft) {
        toast.wtf("$scope.todoDraft does not exist while trying to save todo? Wat.");
        return;
      }

      if ($scope.currentProject) {
        if ($scope.todoDraft.data.tags)
          $scope.todoDraft.data.tags = extractTags($scope.todoDraft.data.tags);

        toast.info("Saving...");
        var req = $scope.todoDraft.save();
        var success = function(data) {
          $scope.$emit("saved", data);
          $scope.cancelEdit($scope.todoDraft.key, true);
          toast.success("Saved");
          toggleTodo(data, "open");
        };

        var error = function(data, status) {
          toast.error("Failed to save", status);
        };
        req.then(success, error);
      } else {
        window.notLoaded();
      }
    };

    $scope.cancelEdit = function(todoKey, justDoIt) { // Nike.
      if (justDoIt || $window.confirm("Are you sure you want to cancel? You will lose all changes!")) {
        $scope.$emit("exitEdit", $scope.todoDraft.key);
        $scope.todoDraft = null;
      }
    };

    // restores the todos that's currently being edited.
    $timeout(function() {
      if ($scope.currently_editing && $scope.currently_editing.indexOf($scope.todo.key) > -1) {
        $scope.editTodo($scope.current_draft_objects[$scope.todo.key], true);
      }
    }, 0);
  }]);

  module.controller("TodosController", ["$scope", "$location", "$window", "toast", "title", "Todos", "ProjectsService", function($scope, $location, $window, toast, title, Todos, ProjectsService) {
    $scope.newtodo = null;
    $scope.todolist = null;
    $scope.todolist_for_template = null;
    $scope.all_expanded = false;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    var regenerate_list_for_template = function() {
      $scope.todolist_for_template = $scope.todolist.todos.values();
    };

    $scope.currently_editing = [];
    // This stores a reference to the object for restoration of the draft
    // when we do some sort of operations on page.
    $scope.current_draft_objects = {};
    $scope.$on("enterEdit", function(e, todo_key, todo_draft) {
      if ($scope.currently_editing.indexOf(todo_key) === -1) {
        $scope.currently_editing.push(todo_key);
        $scope.current_draft_objects[todo_key] = todo_draft;
      }
    });

    var remove_from_currently_editing = function(todo_key) {
      var j = $scope.currently_editing.indexOf(todo_key);
      if (j > -1) {
        $scope.currently_editing.splice(j, 1);
        delete $scope.current_draft_objects[todo_key];
      }
    };

    $scope.$on("exitEdit", function(e, todo_key) {
      remove_from_currently_editing(todo_key);
    });

    var removed = function(e, todo_key) {
      $scope.todolist.todos.remove(todo_key);
      regenerate_list_for_template();
      $scope.todolist.totalTodos--;
      remove_from_currently_editing(todo_key);
    };

    $scope.$on("deleted", removed);
    $scope.$on("archived", removed);

    var add_to_tags_on_save = function(tags) {
      // WARNING: O(n^2) algorithm at least!
      // TODO: sort it, and then insert. O(nlogn) instead. Or when the list
      // is created it could be maintained in order O(nlogn) creation with
      // O(logn) insertion here.
      if (!tags)
        return;

      for (var i=0; i<tags.length; i++) {
        if ($scope.todolist.tags.indexOf(tags[i]) === -1) {
          // This line may push it to O(n^3)
          $scope.todolist.tags.unshift(tags[i]);
          $scope.todolist.toggleFilterTag(tags[i]);
        }
      }
    };

    $scope.$on("saved", function(e, newTodo) {
      var archived = false;
      if (newTodo.archived) {
        archived = newTodo.archived;
        delete newTodo.archived;
      }

      $scope.todolist.todos.put(newTodo.key, new Todos.TodoItem(newTodo.key, $scope.currentProject, newTodo, archived));
      regenerate_list_for_template();
      remove_from_currently_editing(newTodo.key);

      add_to_tags_on_save(newTodo.tags);
    });

    $scope.expand_todos = function() {
      regenerate_list_for_template();
      var list = $scope.todolist_for_template;
      for (var i=0, l=list.length; i<l; i++) {
        toggleTodo(list[i], "open");
      }
      $scope.all_expanded = true;
    };

    $scope.collapse_todos = function() {
      regenerate_list_for_template();
      var list = $scope.todolist_for_template;
      for (var i=0, l=list.length; i<l; i++) {
        toggleTodo(list[i], "close");
      }
      $scope.all_expanded = false;
    };

    $scope.new_todo = function() {
      $scope.newtodo = new Todos.TodoItem(undefined, $scope.currentProject, undefined, $scope.is_archived);
      $("#todos-new-todo").slideDown();
    };

    $scope.cancel_new_todo = function(force) {
      if ($.isEmptyObject($scope.newtodo.data) || force ||
          $window.confirm("Are you sure you want to cancel?")) {
        $scope.newtodo = null;
        $("#todos-new-todo").slideUp();
      }
    };

    $scope.create_todo = function() {
      var invalid_messages = $scope.newtodo.validate(true);
      if (!invalid_messages["invalid"]) {
        if ($scope.newtodo.data.tags)
          $scope.newtodo.data.tags = extractTags($scope.newtodo.data.tags);

        var req = $scope.newtodo.save();
        var success = function(data) {
          $scope.todolist.todos.prepend($scope.newtodo.key, $scope.newtodo);
          regenerate_list_for_template();
          add_to_tags_on_save($scope.newtodo.data.tags);
          $scope.cancel_new_todo(true);
        };

        var error = function(data, status) {
          toast.error("Failed to post", xhr.status);
        };
        req.then(success, error);
      } else {
        // TODO: Need a better way to display these messages in the future.
        toast.warn(invalid_messages["title"]);
      }
    };

    $scope.clear_done = function(todo) {
      var req = $scope.todolist.clearDone();
      var success = function() {
        regenerate_list_for_template();
      };
      var error = function(data, status) {
        toast.error("Failed to clear done", status);
      }
      req.then(success, error);
    };

    $scope.update = function(initial) {
      toast.info("Updating...");
      var req = $scope.todolist.fetch(initial);

      req.then(
        function(data) {
          regenerate_list_for_template();
          toast.close();
        },
        function(data, status) {
          toast.error("Failed to update todos", status);
        }
      );
    };

    $scope.toggle_filter_tag = function(tag) {
      $scope.todolist.toggleFilterTag(tag);
      $scope.update();
    };

    $scope.toggle_show_done = function() {
      $scope.todolist.showdone = !$scope.todolist.showdone;
      $scope.update();
    };

    $scope.toggle_show_notdone = function() {
      $scope.todolist.shownotdone = !$scope.todolist.shownotdone;
      $scope.update();
    };

    $scope.goto = function(page) {
      $scope.todolist.gotopage(page);
    };

    $scope.currentProject = null;
    ProjectsService.getCurrentProject().done(function(currentProject){
      if (currentProject){
        $scope.currentProject = currentProject;
        $scope.todolist = new Todos.TodoList($scope.currentProject, {archived: $scope.is_archived});
        title("Todos", $scope.currentProject);
        $scope.update(true);
        $scope.$$phase || $scope.$apply();
      } else {
        window.notLoaded();
      }
    });
  }]);

  module.controller("SingleTodoController", ["$scope", "$route", "$location", "toast", "title", "Todos", "ProjectsService", function($scope, $route, $location, toast, title, Todos, ProjectsService) {
    $scope.currentProject = null;
    $scope.todo = null;
    $scope.hideCommentLink = true;
    $scope.is_archived = ($location.path().indexOf("archived_todos") !== -1)

    var removed = function(e, todo_key) {
      $location.path("/projects/" + $scope.currentProject.key + "/todos");
      $location.replace();
    };
    $scope.$on("deleted", removed);
    $scope.$on("archived", removed);

    var refresh_comments = function() {
      $scope.comments = $scope.todo.data.children;
      $scope.commentsParent = $scope.todo;
    };

    $scope.$on("saved", function(e, new_todo) {
      var archived = false;
      if (new_todo.archived) {
        archived = new_todo.archived;
        delete new_todo.archived;
      }

      $scope.todo = new Todos.TodoItem(new_todo.key, $scope.currentProject, new_todo, archived);
      refresh_comments();
    });

    $scope.update = function() {
      $scope.todo = new Todos.TodoItem($route.current.params.todoId, $scope.currentProject, undefined, $scope.is_archived);
      var req = $scope.todo.refresh();
      var success = function() {
        toast.loaded();
        refresh_comments();
        toggleTodo($scope.todo, "open", true);
      };
      var error = function(data, status) {
        toast.error("Failed to load todos", status);
      };

      req.then(success, error);
    };

    ProjectsService.getCurrentProject().done(function(currentProject) {
      $scope.currentProject = currentProject;
      $scope.update();
      $scope.$$phase || $scope.$apply();
    }).fail(function(xhr) {
      toast.error("Failed to get project info", xhr.status);
    });
  }]);
})();
<|endoftext|>


<commit_before>const gulp = require('gulp');
const babel = require('gulp-babel');
const sourcemaps = require('gulp-sourcemaps');
const changed = require('gulp-changed');
const eslint = require('gulp-eslint');

gulp.task('lint', function() {
  return gulp.src('src/**/*.js')
    //.pipe(changed('lib'))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('compile', ['lint'], () => {
  return gulp.src('src/**/*.js')
    .pipe(changed('lib'))
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('lib'));
});

gulp.task('watch', () => {
  gulp.watch('src/**/*.js', ['lint', 'compile']);
});

gulp.task('default', ['watch']);
<commit_msg>update gulpfile<commit_after>const gulp = require('gulp');
const babel = require('gulp-babel');
const sourcemaps = require('gulp-sourcemaps');
const changed = require('gulp-changed');
const eslint = require('gulp-eslint');

gulp.task('lint', function() {
  return gulp.src('src/**/*.js')
    //.pipe(changed('lib'))
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('compile', ['lint'], () => {
  return gulp.src('src/**/*.js')
    //.pipe(changed('lib'))
    .pipe(sourcemaps.init())
    .pipe(babel())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('lib'));
});

gulp.task('watch', () => {
  gulp.watch('src/**/*.js', ['lint', 'compile']);
});

gulp.task('default', ['watch']);
<|endoftext|>