<commit_before>/*jslint node: true */
/*jslint asi: true */
/* Copyright (c) 2013 Richard Rodger, MIT License */
"use strict";

var fs      = require('fs')
var path    = require('path')
var _       = require('underscore')
var uuid    = require('node-uuid')
var levelup = require('levelup')
var name    = "level-store"

var levelQuery      = require('level-queryengine')
var jsonqueryEngine = require('jsonquery-engine')

module.exports = function(opts, register) {
  var desc, dbmap = {}, seneca = this

  opts = this.util.deepextend({
    folder: '.',
    encoding: 'json',
    sync: false,
    fillCache: true
  }, opts)

  function fixquery(qent, q) {
    return _.isString(q) ? {id: q} : _.isString(q.id) ? q : {}
  }

  function metaquery(qent,q) {
    var mq = {}

    if( !q.native$ ) {

      if( q.limit$ && !q.skip$) {
        mq.limit = q.limit$
      }

    }
    else {
      mq = q.native$
    }

    return mq
  }

  function filterdata(q, data) {

    for(var p in q) {
      if( !~p.indexOf('$') && q[p] != data[p] ) {
        return null
      }
    }

    if( q.fields$ ) {
      data = _.omit(data, q.field$)
    }

    return data
  }

  function fixlist(q, list) {

    // sort first
    if( q.sort$ ) {
      for( var sf in q.sort$ ) break;
      var sd = q.sort$[sf] < 0 ? -1 : 1

      list = list.sort(function(a, b){
        return sd * ( a[sf] < b[sf] ? -1 : a[sf] === b[sf] ? 0 : 1 )
      })
    }

    if( q.skip$ ) {
      list = list.slice(q.skip$)
    }

    if( q.limit$ ) {
      list = list.slice(0, q.limit$)
    }

    return list
  }

  function ensurefolder(folder, cb){
    fs.exists(folder, function(exists){
      if( exists ) return cb();

      fs.mkdir(folder, function(err){
        cb(err)
      })
    })
  }

  function makefolderpath(ent) {
    var canon = ent.canon$({object: true})
    var base  = canon.base
    var name  = canon.name

    var entfolder = (base ? base + '_' : '') + name
    var folderpath = path.join(opts.folder, entfolder)

    return folderpath
  }

  function error(done, win){
    return function(err, out){
      if( err ) return done(err);
      if (win) win(out)
    }
  }

  var get_db = once(function get_db(ent, done) {
    var folder = makefolderpath(ent)
    var db = dbmap[folder]

    if( !db ) {
      ensurefolder(folder, error(done, function(){
        if( db = dbmap[folder] ) return done(null,db);

        try {
          var n = 0
          db = dbmap[folder] = levelQuery(levelup(folder, opts))
          db.query.use(jsonqueryEngine());

          // index all the properties in pairs
          db.ensureIndex('*', 'pairs', pairs.index);

        }
        catch(e) {
          if( db = dbmap[folder] )
            return done(null, db);
          return done(e);
        }
        return done(null, db)
      }))
    }
    else return done(null, db);
  })

  function once (fun) {
    return function () {
      var args = [].slice.call(arguments)
      var cb = args.pop()
      var n = 0
      args.push(function (err, val, val2) {
        if(n++)
          return seneca.emit('error', new Error('callback twice!'))
        cb(err, val, val2)
      })
      return fun.apply(this, args)
    }
  }

  var store = {
    name:name,

    close: once(function(done) {
      seneca.util.recurse(_.values(dbmap), function(db, next){
        db.close(next)
      },done)
    }),

    save: once(function(args, done) {
      var ent = args.ent

      var update = !!ent.id

      if( !update ) {
        ent.id = void 0 != ent.id$ ? ent.id$ : uuid();
        delete(ent.id$)
      }

      once(get_db)(ent, error(done, function(db){
        db.put( ent.id, ent.data$(false), {sync:opts.sync}, error(done, function(){
          seneca.log.debug('save/'+(update? 'update' : 'insert'), ent, desc)
          done(null, ent)
        }))
      }))
    }),

    load: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      var qq = fixquery(qent, q)

      if( qq.id ) {
        get_db(qent, error(done, function(db){
          db.get( qq.id, {fillCache:opts.fillCache}, function(err, data){
            if( err ) {
              if( 'NotFoundError' == err.name ) return done(null, null);
              return done(err);
            }
            var fent = qent.make$(data)
            seneca.log.debug('load', q, fent, desc)
            done(null, fent)
          })
        }))
      }
      else {
        store.list(args, error(done, function(list){
          done(null, list[0])
        }))
      }
    }),

    remove: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      // all that match the query, of course
      var all  = q.all$ // default false

      var load  = _.isUndefined(q.load$) ? true : q.load$ // default true

      var qq = fixquery(qent,q)

      get_db(qent, error(done, function(db){
        if( !_.isUndefined(qq.id) && load && !all ) {
          db.get( qq.id, {fillCache:opts.fillCache}, function(err, data){
            if( err ) {
              if( 'NotFoundError' == err.name ) return done(null, null);
              return done(err);
            }
            var fent = qent.make$(data)
            do_remove(db, fent)
          })
        }
        else do_remove(db)
      }))

      function do_remove(db, maybefent) {
        if( all || _.isUndefined(qq.id) ) {
          store.list(args, error(done, function(list){
            seneca.util.recurse(
              list,
              function(fent, next){
                db.del(fent.id, {sync:opts.sync}, next)
              },
              function(err){
                seneca.log.debug('remove/all', q, desc)
                done(err)
              }
            )
          }))

        }
        else {
          db.del(qq.id, {sync:opts.sync}, function(err){
            if( err ) return done(err)
            seneca.log.debug('remove/one', q, maybefent, desc)
            done(null, maybefent)
          })
        }
      }
    }),

    list: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      get_db(qent, error(done, function(db){

        var mq = metaquery(qent, q)

        var n = 1

        var list = []

        if(q.all$)
          q = {}
        db.query(q)
          .on('data', function (data) {

            if( filterdata( q, data ) ) {
              list.push( qent.make$(data) )
            }

          })
          .on('error', function (err) {
            if(--n) throw new Error('errored:'+ n)
            console.log('ERR')
            done(err)
          })
          .on('close', function () {
            // do nothing, I guess
          })
          .on('end', function () {
            if(--n) throw new Error('ended:'+ n)

            list = fixlist(q,list)

            seneca.log.debug('list',q,list.length,list[0],desc)
            console.log('cb!', list.length)
            done(null,list)
          })
      }))
    }),

    native: once(function(args,done) {
      get_db(args.qent, function(err, db) {
        done(err, db);
      });
    })
  }

  seneca.store.init(seneca,opts,store,function(err,tag,description){
    if( err ) return register(err);

    desc = description

    register(null,{name:store.name,tag:tag})
  })
}

<commit_msg>level instead of levelup<commit_after>/*jslint node: true */
/*jslint asi: true */
/* Copyright (c) 2013 Richard Rodger, MIT License */
"use strict";

var fs      = require('fs')
var path    = require('path')
var _       = require('underscore')
var uuid    = require('node-uuid')
var levelup = require('level')
var name    = "level-store"

var levelQuery      = require('level-queryengine')
var jsonqueryEngine = require('jsonquery-engine')

module.exports = function(opts, register) {
  var desc, dbmap = {}, seneca = this

  opts = this.util.deepextend({
    folder: '.',
    encoding: 'json',
    sync: false,
    fillCache: true
  }, opts)

  function fixquery(qent, q) {
    return _.isString(q) ? {id: q} : _.isString(q.id) ? q : {}
  }

  function metaquery(qent,q) {
    var mq = {}

    if( !q.native$ ) {

      if( q.limit$ && !q.skip$) {
        mq.limit = q.limit$
      }

    }
    else {
      mq = q.native$
    }

    return mq
  }

  function filterdata(q, data) {

    for(var p in q) {
      if( !~p.indexOf('$') && q[p] != data[p] ) {
        return null
      }
    }

    if( q.fields$ ) {
      data = _.omit(data, q.field$)
    }

    return data
  }

  function fixlist(q, list) {

    // sort first
    if( q.sort$ ) {
      for( var sf in q.sort$ ) break;
      var sd = q.sort$[sf] < 0 ? -1 : 1

      list = list.sort(function(a, b){
        return sd * ( a[sf] < b[sf] ? -1 : a[sf] === b[sf] ? 0 : 1 )
      })
    }

    if( q.skip$ ) {
      list = list.slice(q.skip$)
    }

    if( q.limit$ ) {
      list = list.slice(0, q.limit$)
    }

    return list
  }

  function ensurefolder(folder, cb){
    fs.exists(folder, function(exists){
      if( exists ) return cb();

      fs.mkdir(folder, function(err){
        cb(err)
      })
    })
  }

  function makefolderpath(ent) {
    var canon = ent.canon$({object: true})
    var base  = canon.base
    var name  = canon.name

    var entfolder = (base ? base + '_' : '') + name
    var folderpath = path.join(opts.folder, entfolder)

    return folderpath
  }

  function error(done, win){
    return function(err, out){
      if( err ) return done(err);
      if (win) win(out)
    }
  }

  var get_db = once(function get_db(ent, done) {
    var folder = makefolderpath(ent)
    var db = dbmap[folder]

    if( !db ) {
      ensurefolder(folder, error(done, function(){
        if( db = dbmap[folder] ) return done(null,db);

        try {
          var n = 0
          db = dbmap[folder] = levelQuery(levelup(folder, opts))
          db.query.use(jsonqueryEngine());

          // index all the properties in pairs
          db.ensureIndex('*', 'pairs', pairs.index);

        }
        catch(e) {
          if( db = dbmap[folder] )
            return done(null, db);
          return done(e);
        }
        return done(null, db)
      }))
    }
    else return done(null, db);
  })

  function once (fun) {
    return function () {
      var args = [].slice.call(arguments)
      var cb = args.pop()
      var n = 0
      args.push(function (err, val, val2) {
        if(n++)
          return seneca.emit('error', new Error('callback twice!'))
        cb(err, val, val2)
      })
      return fun.apply(this, args)
    }
  }

  var store = {
    name:name,

    close: once(function(done) {
      seneca.util.recurse(_.values(dbmap), function(db, next){
        db.close(next)
      },done)
    }),

    save: once(function(args, done) {
      var ent = args.ent

      var update = !!ent.id

      if( !update ) {
        ent.id = void 0 != ent.id$ ? ent.id$ : uuid();
        delete(ent.id$)
      }

      once(get_db)(ent, error(done, function(db){
        db.put( ent.id, ent.data$(false), {sync:opts.sync}, error(done, function(){
          seneca.log.debug('save/'+(update? 'update' : 'insert'), ent, desc)
          done(null, ent)
        }))
      }))
    }),

    load: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      var qq = fixquery(qent, q)

      if( qq.id ) {
        get_db(qent, error(done, function(db){
          db.get( qq.id, {fillCache:opts.fillCache}, function(err, data){
            if( err ) {
              if( 'NotFoundError' == err.name ) return done(null, null);
              return done(err);
            }
            var fent = qent.make$(data)
            seneca.log.debug('load', q, fent, desc)
            done(null, fent)
          })
        }))
      }
      else {
        store.list(args, error(done, function(list){
          done(null, list[0])
        }))
      }
    }),

    remove: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      // all that match the query, of course
      var all  = q.all$ // default false

      var load  = _.isUndefined(q.load$) ? true : q.load$ // default true

      var qq = fixquery(qent,q)

      get_db(qent, error(done, function(db){
        if( !_.isUndefined(qq.id) && load && !all ) {
          db.get( qq.id, {fillCache:opts.fillCache}, function(err, data){
            if( err ) {
              if( 'NotFoundError' == err.name ) return done(null, null);
              return done(err);
            }
            var fent = qent.make$(data)
            do_remove(db, fent)
          })
        }
        else do_remove(db)
      }))

      function do_remove(db, maybefent) {
        if( all || _.isUndefined(qq.id) ) {
          store.list(args, error(done, function(list){
            seneca.util.recurse(
              list,
              function(fent, next){
                db.del(fent.id, {sync:opts.sync}, next)
              },
              function(err){
                seneca.log.debug('remove/all', q, desc)
                done(err)
              }
            )
          }))

        }
        else {
          db.del(qq.id, {sync:opts.sync}, function(err){
            if( err ) return done(err)
            seneca.log.debug('remove/one', q, maybefent, desc)
            done(null, maybefent)
          })
        }
      }
    }),

    list: once(function(args, done) {
      var qent = args.qent
      var q    = args.q

      get_db(qent, error(done, function(db){

        var mq = metaquery(qent, q)

        var n = 1

        var list = []

        if(q.all$)
          q = {}
        db.query(q)
          .on('data', function (data) {

            if( filterdata( q, data ) ) {
              list.push( qent.make$(data) )
            }

          })
          .on('error', function (err) {
            if(--n) throw new Error('errored:'+ n)
            console.log('ERR')
            done(err)
          })
          .on('close', function () {
            // do nothing, I guess
          })
          .on('end', function () {
            if(--n) throw new Error('ended:'+ n)

            list = fixlist(q,list)

            seneca.log.debug('list',q,list.length,list[0],desc)
            console.log('cb!', list.length)
            done(null,list)
          })
      }))
    }),

    native: once(function(args,done) {
      get_db(args.qent, function(err, db) {
        done(err, db);
      });
    })
  }

  seneca.store.init(seneca,opts,store,function(err,tag,description){
    if( err ) return register(err);

    desc = description

    register(null,{name:store.name,tag:tag})
  })
}

<|endoftext|>


<commit_before>'use strict'

window.onload = function() {
  clock();
  loadOptions();
}

var SETTINGS = JSON.parse(localStorage.getItem('userOptions'));

var commands = [
  { command: 'g', url: 'https://www.google.com', search: '/search?q=' },
  { command: 'r', url: 'https://www.reddit.com', search: '/r/' },
  { command: 'y', url: 'https://www.youtube.com', search: '/results?search_query=' },
  { command: 'a', url: 'https://smile.amazon.com', search: '/s/?field-keywords=' },
  { command: 'w', url: 'https://www.wikipedia.org', search: '/w/index.php?title=Special:Search&search=' },
  { command: 'wa', url: 'https://www.wolframalpha.com', search: '/input/?i=' },
  { command: 'imdb', url: 'https://www.imdb.com', search: '/find?s=all&q=' },
  { command: 'img', url: 'https://www.google.com', search: '/search?tbm=isch&q=' },
  { command: 't', url: '', search: '' }
];

// Input
function verifyKey(e) {
  var keycode;
  if (window.event) {
    keycode = window.event.keyCode;
  } else if (e) {
    keycode = e.which;
  }
  if (keycode == 13) { // Enter/return key
    clearContent();
    interpret();
  }
  checkInputLength();
}

function clearInput() {
  var input = document.getElementById('input-box');
  input.value = '';
  input.select();
}

function checkInputLength() {
  var input = document.getElementById('input-box');
  if (input.value.length > 20) {
    input.size = input.value.length + 1;
  } else {
    input.size = 20;
  }
}

function getFullCommand(c) {
  for (var i=0; i < commands.length; i++) {
    if (c === commands[i].command) {
      return commands[i];
    }
  }
  return null;
}

function queryFix(command, query) {
  query = (command.command === 'w' || command.command === 'wa')
    ? query.trim().replace(/ /g, '+')
    : query.trim();
  return query
}

function interpret() {
  var inputBox = document.getElementById('input-box');
  inputBox.select();
  var input = inputBox.value.trim();
  if (input === '') {
    lowerWrapper();
    return;
  }

  if (input === 'help' || input === '?') {
    displayHelpMenu();
    return;
  } else if (input === 'options' || input === 'settings') {
    displayOptionsMenu();
    return;
  }

  var inputArr = input.split(';');
  var newtab = (inputArr[inputArr.length-1] === 'n');
  var command; var query;

  var validCommand = false;
  command = getFullCommand(inputArr[0]);
  if (command !== null) {
    validCommand = true;
  }

  if (validCommand) {
    query = queryFix(command, inputArr[1]);
    switch(inputArr.length) {
      case 1:
        redirect(command.url, newtab);
        return false;
        break;
      case 2:
        if (inputArr[1] === 'n') {
          redirect(command.url, newtab);
          return false;
        } else {
          redirect(command.url + command.search + query, newtab);
          return false;
        }
        break;
      default:
        redirect(command.url + command.search + query, newtab);
        return false;
    }
    redirect(command.url + command.search + query, newtab);
    return false;
  } else {
    command = SETTINGS.defaultCommand;
    query = queryFix(command, inputArr[0]);
    redirect(command.url + command.search + query, newtab);
    return false;
  }
}

function redirect(url, newtab) {
  url = (!url.startsWith('http'))
    ? 'https://' + url
    : url;
  if (newtab || SETTINGS.alwaysNewTab) {
    var win = window.open(url);
    win.focus();
    return false;
  } else {
    window.location.href = url;
    return false;
  }
}

// Options
function saveOptions() {
  if (typeof(Storage) == "undefined") {
    alert("Browser does not support local storage: your settings won't be saved (sorry)");
  } else {
    // Background color
    var color = document.getElementById('bgColorInput').value;
    if (!color.startsWith('#')) {
      color = '#' + color;
    }
    if (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color)) { // check if valid hex value
      SETTINGS.color = color;
      setColor(color);
      localStorage.setItem('userOptions', JSON.stringify(SETTINGS));
    } else {
      alert('not a valid hex value\n(valid example: #A1C0C0)');
      return false;
    }

    // Get default command
    var radios = document.getElementById('defaultCommandForm');
    var defaultCommand = null;
    for (var i=0; i < radios.length; i++) {
      if (radios[i].checked) {
        defaultCommand = radios[i].value;
        break;
      }
    }
    defaultCommand = getFullCommand(defaultCommand);
    if (defaultCommand !== null) {
      SETTINGS.defaultCommand = defaultCommand;
    }

    // Tab open style
    SETTINGS.alwaysNewTab = document.getElementById('openStyleCheckbox').checked;
  }
  clearInput();
  return true;
}

function loadOptions() {
  if (typeof(Storage) !== 'undefined') {
    if (localStorage.getItem('userOptions') !== null) {
      SETTINGS = JSON.parse(localStorage.getItem('userOptions'));
      setColor(SETTINGS.color);
    } else {
      var defaultSettings = {
        defaultCommand: {
          command: 'g',
          url: 'https://www.google.com',
          search: '/search?q='
        },
        alwaysNewtab: false,
        color: "#A1C0C0"
      };
      localStorage.setItem('userOptions', JSON.stringify(defaultSettings));
      SETTINGS = JSON.parse(localStorage.getItem('userOptions'));
    }
  }
}

function setColor(color) {
  document.body.style.backgroundColor = color;
}

// Displayed content
function clearMessage() {
  var div = document.getElementById('message');
  div.innerHTML = '';
  div.style.display = 'none';
}

function displayMessage(message, timeMs) {
  var div = document.getElementById('message');
  div.style.display = ''; // Show div
  div.innerHTML = message;
  if (timeMs !== 0) {
    setTimeout(clearMessage, timeMs);
  }
}

function clearContent() {
  document.getElementById('content').innerHTML = '';
}

function displayContent(content) {
  clearContent();
  document.getElementById('content').innerHTML = content;
  window.scrollBy(0, 1000);
}

function raiseWrapper() {
  document.getElementById('wrapper').style.top = "10%";
}

function lowerWrapper() {
  document.getElementById('wrapper').style.top = "35%";
}

function displayOptionsMenu() {
  var html = "\

 \

 \

 \
       Default Command
executes if no command was specified	 \

 \

 \
        \
          <form id='defaultCommandForm'> \
             <input type='radio' name='defaultCommandRadio' value='t'>Go to website
 \
             <input type='radio' name='defaultCommandRadio' value='g'>Google search
 \
             <input type='radio' name='defaultCommandRadio' value='w'>Wikipedia search
 \
             <input type='radio' name='defaultCommandRadio' value='y'>YouTube search
 \
             <input type='radio' name='defaultCommandRadio' value='a'>Amazon search
 \
             <input type='radio' name='defaultCommandRadio' value='imdb'>IMDB search
 \
             <input type='radio' name='defaultCommandRadio' value='img'>Google Images search
 \
             <input type='radio' name='defaultCommandRadio' value='wa'>Wolfram Alpha search
 \
             <input type='radio' name='defaultCommandRadio' value='r'>Go to subreddit \
          </form> \
       	 \

 \

 \
       Open Style	 \

 \

 \
        \
          <input type='checkbox' id='openStyleCheckbox' value='newTab'>Always open in new tab
 \
       	 \

 \

 \
       Background Color	 \

 \

 \
        \
          Color: <input type='text' id='bgColorInput' placeholder='#A1C0C0' size='7' spellcheck='false'> \
          Color Picker \
       	 \

 \

 \
        \
          <button type='button' id='saveOptionsBtn' class='menuBtn'>Done</button> \
       	 \

 \

";

  raiseWrapper();
  displayContent(html);

  document.getElementById('saveOptionsBtn').onclick = function() {
    if (saveOptions()) {
      lowerWrapper();
      clearContent();
      displayMessage('settings saved', 2000);
    }
  };

  // Display saved options
  var radios = document.getElementById('defaultCommandForm');
  for (var i=0; i < radios.length; i++) {
    if (SETTINGS.defaultCommand.command === radios[i].value) {
      radios[i].checked = true;
      break;
    }
  }
  document.getElementById('openStyleCheckbox').checked = SETTINGS.alwaysNewTab;
  document.getElementById('bgColorInput').value = SETTINGS.color;
}

function displayHelpMenu() {
  var html = " \

syntax:
command;query[;n]
 \

 \

 \
        Command	 \
        Description	 \

 \

 \
        options	 \
        show options menu	 \

 \
        r;&ltsubreddit&gt	 \
        go to subreddit	 \

 \

 \
        g;&ltquery&gt	 \
        google search	 \

 \

 \
        y;&ltquery&gt	 \
        youtube search	 \

 \

 \
        a;&ltquery&gt	 \
        amazon search	 \

 \

 \
        w;&ltquery&gt	 \
        wikipedia search	 \

 \

 \
        imdb;&ltquery&gt	 \
        imdb search	 \

 \

 \
        img;&ltquery&gt	 \
        google images search	 \

 \

 \
        wa;&ltquery&gt	 \
        wolfram alpha search	 \

 \

 \
        t;&lturl&gt	 \
        open url in current tab	 \

 \

 \
        &ltcommand&gt;n	 \
        open action in new tab	 \

 \

 \
        help | ?	 \
        show this text	 \

 \

 \
         \
          <button type='button' id='hideHelpBtn' class='menuBtn'>Hide</button> \
        	 \

 \

"

  raiseWrapper();
  displayContent(html);

  document.getElementById('hideHelpBtn').onclick = function() {
    clearContent();
    clearInput();
    lowerWrapper();
  }
}

// Clock
function clock() {
  var date = new Date();
  var h = date.getHours();
  h = (h > 12) ? (checkTime(h -= 12)) : checkTime(h); // 12hr clock
  var m = checkTime(date.getMinutes());
  document.getElementById('clock').innerHTML = h + ':' + m;
  setTimeout(clock, 1000);
}
function checkTime(n) {
  n = (n < 10) ? (n = '0' + n) : n;
  return n;
}
<commit_msg>Display help menu on clock click<commit_after>'use strict'

window.onload = function() {
  clock();
  loadOptions();
  document.getElementById('clock').addEventListener('click', displayHelpMenu);
}

var SETTINGS = JSON.parse(localStorage.getItem('userOptions'));

var commands = [
  { command: 'g', url: 'https://www.google.com', search: '/search?q=' },
  { command: 'r', url: 'https://www.reddit.com', search: '/r/' },
  { command: 'y', url: 'https://www.youtube.com', search: '/results?search_query=' },
  { command: 'a', url: 'https://smile.amazon.com', search: '/s/?field-keywords=' },
  { command: 'w', url: 'https://www.wikipedia.org', search: '/w/index.php?title=Special:Search&search=' },
  { command: 'wa', url: 'https://www.wolframalpha.com', search: '/input/?i=' },
  { command: 'imdb', url: 'https://www.imdb.com', search: '/find?s=all&q=' },
  { command: 'img', url: 'https://www.google.com', search: '/search?tbm=isch&q=' },
  { command: 't', url: '', search: '' }
];

// Input
function verifyKey(e) {
  var keycode;
  if (window.event) {
    keycode = window.event.keyCode;
  } else if (e) {
    keycode = e.which;
  }
  if (keycode == 13) { // Enter/return key
    clearContent();
    interpret();
  }
  checkInputLength();
}

function clearInput() {
  var input = document.getElementById('input-box');
  input.value = '';
  input.select();
}

function checkInputLength() {
  var input = document.getElementById('input-box');
  if (input.value.length > 20) {
    input.size = input.value.length + 1;
  } else {
    input.size = 20;
  }
}

function getFullCommand(c) {
  for (var i=0; i < commands.length; i++) {
    if (c === commands[i].command) {
      return commands[i];
    }
  }
  return null;
}

function queryFix(command, query) {
  query = (command.command === 'w' || command.command === 'wa')
    ? query.trim().replace(/ /g, '+')
    : query.trim();
  return query
}

function interpret() {
  var inputBox = document.getElementById('input-box');
  inputBox.select();
  var input = inputBox.value.trim();
  if (input === '') {
    lowerWrapper();
    return;
  }

  if (input === 'help' || input === '?') {
    displayHelpMenu();
    return;
  } else if (input === 'options' || input === 'settings') {
    displayOptionsMenu();
    return;
  }

  var inputArr = input.split(';');
  var newtab = (inputArr[inputArr.length-1] === 'n');
  var command; var query;

  var validCommand = false;
  command = getFullCommand(inputArr[0]);
  if (command !== null) {
    validCommand = true;
  }

  if (validCommand) {
    query = queryFix(command, inputArr[1]);
    switch(inputArr.length) {
      case 1:
        redirect(command.url, newtab);
        return false;
        break;
      case 2:
        if (inputArr[1] === 'n') {
          redirect(command.url, newtab);
          return false;
        } else {
          redirect(command.url + command.search + query, newtab);
          return false;
        }
        break;
      default:
        redirect(command.url + command.search + query, newtab);
        return false;
    }
    redirect(command.url + command.search + query, newtab);
    return false;
  } else {
    command = SETTINGS.defaultCommand;
    query = queryFix(command, inputArr[0]);
    redirect(command.url + command.search + query, newtab);
    return false;
  }
}

function redirect(url, newtab) {
  url = (!url.startsWith('http'))
    ? 'https://' + url
    : url;
  if (newtab || SETTINGS.alwaysNewTab) {
    var win = window.open(url);
    win.focus();
    return false;
  } else {
    window.location.href = url;
    return false;
  }
}

// Options
function saveOptions() {
  if (typeof(Storage) == "undefined") {
    alert("Browser does not support local storage: your settings won't be saved (sorry)");
  } else {
    // Background color
    var color = document.getElementById('bgColorInput').value;
    if (!color.startsWith('#')) {
      color = '#' + color;
    }
    if (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(color)) { // check if valid hex value
      SETTINGS.color = color;
      setColor(color);
      localStorage.setItem('userOptions', JSON.stringify(SETTINGS));
    } else {
      alert('not a valid hex value\n(valid example: #A1C0C0)');
      return false;
    }

    // Get default command
    var radios = document.getElementById('defaultCommandForm');
    var defaultCommand = null;
    for (var i=0; i < radios.length; i++) {
      if (radios[i].checked) {
        defaultCommand = radios[i].value;
        break;
      }
    }
    defaultCommand = getFullCommand(defaultCommand);
    if (defaultCommand !== null) {
      SETTINGS.defaultCommand = defaultCommand;
    }

    // Tab open style
    SETTINGS.alwaysNewTab = document.getElementById('openStyleCheckbox').checked;
  }
  clearInput();
  return true;
}

function loadOptions() {
  if (typeof(Storage) !== 'undefined') {
    if (localStorage.getItem('userOptions') !== null) {
      SETTINGS = JSON.parse(localStorage.getItem('userOptions'));
      setColor(SETTINGS.color);
    } else {
      var defaultSettings = {
        defaultCommand: {
          command: 'g',
          url: 'https://www.google.com',
          search: '/search?q='
        },
        alwaysNewtab: false,
        color: "#A1C0C0"
      };
      localStorage.setItem('userOptions', JSON.stringify(defaultSettings));
      SETTINGS = JSON.parse(localStorage.getItem('userOptions'));
    }
  }
}

function setColor(color) {
  document.body.style.backgroundColor = color;
}

// Displayed content
function clearMessage() {
  var div = document.getElementById('message');
  div.innerHTML = '';
  div.style.display = 'none';
}

function displayMessage(message, timeMs) {
  var div = document.getElementById('message');
  div.style.display = ''; // Show div
  div.innerHTML = message;
  if (timeMs !== 0) {
    setTimeout(clearMessage, timeMs);
  }
}

function clearContent() {
  document.getElementById('content').innerHTML = '';
}

function displayContent(content) {
  clearContent();
  document.getElementById('content').innerHTML = content;
  window.scrollBy(0, 1000);
}

function raiseWrapper() {
  document.getElementById('wrapper').style.top = "10%";
}

function lowerWrapper() {
  document.getElementById('wrapper').style.top = "35%";
}

function displayOptionsMenu() {
  var html = "\

 \

 \

 \
       Default Command
executes if no command was specified	 \

 \

 \
        \
          <form id='defaultCommandForm'> \
             <input type='radio' name='defaultCommandRadio' value='t'>Go to website
 \
             <input type='radio' name='defaultCommandRadio' value='g'>Google search
 \
             <input type='radio' name='defaultCommandRadio' value='w'>Wikipedia search
 \
             <input type='radio' name='defaultCommandRadio' value='y'>YouTube search
 \
             <input type='radio' name='defaultCommandRadio' value='a'>Amazon search
 \
             <input type='radio' name='defaultCommandRadio' value='imdb'>IMDB search
 \
             <input type='radio' name='defaultCommandRadio' value='img'>Google Images search
 \
             <input type='radio' name='defaultCommandRadio' value='wa'>Wolfram Alpha search
 \
             <input type='radio' name='defaultCommandRadio' value='r'>Go to subreddit \
          </form> \
       	 \

 \

 \
       Open Style	 \

 \

 \
        \
          <input type='checkbox' id='openStyleCheckbox' value='newTab'>Always open in new tab
 \
       	 \

 \

 \
       Background Color	 \

 \

 \
        \
          Color: <input type='text' id='bgColorInput' placeholder='#A1C0C0' size='7' spellcheck='false'> \
          Color Picker \
       	 \

 \

 \
        \
          <button type='button' id='saveOptionsBtn' class='menuBtn'>Done</button> \
       	 \

 \

";

  raiseWrapper();
  displayContent(html);

  document.getElementById('saveOptionsBtn').onclick = function() {
    if (saveOptions()) {
      lowerWrapper();
      clearContent();
      displayMessage('settings saved', 2000);
    }
  };

  // Display saved options
  var radios = document.getElementById('defaultCommandForm');
  for (var i=0; i < radios.length; i++) {
    if (SETTINGS.defaultCommand.command === radios[i].value) {
      radios[i].checked = true;
      break;
    }
  }
  document.getElementById('openStyleCheckbox').checked = SETTINGS.alwaysNewTab;
  document.getElementById('bgColorInput').value = SETTINGS.color;
}

function displayHelpMenu() {
  var html = " \

syntax:
command;query[;n]
 \

 \

 \
        Command	 \
        Description	 \

 \

 \
        options	 \
        show options menu	 \

 \
        r;&ltsubreddit&gt	 \
        go to subreddit	 \

 \

 \
        g;&ltquery&gt	 \
        google search	 \

 \

 \
        y;&ltquery&gt	 \
        youtube search	 \

 \

 \
        a;&ltquery&gt	 \
        amazon search	 \

 \

 \
        w;&ltquery&gt	 \
        wikipedia search	 \

 \

 \
        imdb;&ltquery&gt	 \
        imdb search	 \

 \

 \
        img;&ltquery&gt	 \
        google images search	 \

 \

 \
        wa;&ltquery&gt	 \
        wolfram alpha search	 \

 \

 \
        t;&lturl&gt	 \
        open url in current tab	 \

 \

 \
        &ltcommand&gt;n	 \
        open action in new tab	 \

 \

 \
        help | ?	 \
        show this text	 \

 \

 \
         \
          <button type='button' id='hideHelpBtn' class='menuBtn'>Hide</button> \
        	 \

 \

"

  raiseWrapper();
  displayContent(html);

  document.getElementById('hideHelpBtn').onclick = function() {
    clearContent();
    clearInput();
    lowerWrapper();
  }
}

// Clock
function clock() {
  var date = new Date();
  var h = date.getHours();
  h = (h > 12) ? (checkTime(h -= 12)) : checkTime(h); // 12hr clock
  var m = checkTime(date.getMinutes());
  document.getElementById('clock').innerHTML = h + ':' + m;
  setTimeout(clock, 1000);
}
function checkTime(n) {
  n = (n < 10) ? (n = '0' + n) : n;
  return n;
}
<|endoftext|>


<commit_before>'use strict'

const Mocha = require('mocha')
const coMocha = require('co-mocha')
const chai = require('chai')

const spawn = require('child_process').spawn

const commonTags = require('common-tags')
const TemplateTag = commonTags.TemplateTag
const stripIndentTransformer = commonTags.stripIndentTransformer
const trimResultTransformer = commonTags.trimResultTransformer
const replaceResultTransformer = commonTags.replaceResultTransformer

const stripIndent = new TemplateTag(
  stripIndentTransformer,
  replaceResultTransformer(/\n(\n*)\s*?$/, '$1'),
  replaceResultTransformer(/^\n/, '')
)

function _run_cmd(cmd, args) {
	return new Promise((res, rej) => {
		const child = spawn(cmd, args)
		let resp = ''
		child.stdout.on('data', function (buffer) {
			resp += buffer.toString()
		})
		child.stdout.on('end', function() {
			res(resp)
		})
		child.stdout.on('error', (err) => rej(err))
	})
}

coMocha(Mocha)
global.mocha = Mocha
global.expect = chai.expect

global.helper = {
	npm: {
		install: function (module) {
			return _run_cmd('npm', ['install', module])
		},
		uninstall: function (module) {
			return _run_cmd('npm', ['uninstall', module])
		}
	},
	stripIndent: stripIndent
}
<commit_msg>Implements code from declandewet/common-tags/issues/37<commit_after>'use strict'

const Mocha = require('mocha')
const coMocha = require('co-mocha')
const chai = require('chai')

const spawn = require('child_process').spawn

const commonTags = require('common-tags')
const TemplateTag = commonTags.TemplateTag
const stripIndentTransformer = commonTags.stripIndentTransformer
const trimResultTransformer = commonTags.trimResultTransformer
const replaceResultTransformer = commonTags.replaceResultTransformer

const stripIndent = new TemplateTag(
		stripIndentTransformer,
		trimResultTransformer('left'),
		replaceResultTransformer(/\n(\n*)\s*?$/, '$1')
)

function _run_cmd(cmd, args) {
	return new Promise((res, rej) => {
		const child = spawn(cmd, args)
		let resp = ''
		child.stdout.on('data', function (buffer) {
			resp += buffer.toString()
		})
		child.stdout.on('end', function() {
			res(resp)
		})
		child.stdout.on('error', (err) => rej(err))
	})
}

coMocha(Mocha)
global.mocha = Mocha
global.expect = chai.expect

global.helper = {
	npm: {
		install: function (module) {
			return _run_cmd('npm', ['install', module])
		},
		uninstall: function (module) {
			return _run_cmd('npm', ['uninstall', module])
		}
	},
	stripIndent: stripIndent
}
<|endoftext|>


<commit_before>'use strict'

const log = require('util').debuglog('cloudfoundry-actuator-middleware');

const HttpAdapter = require('./http-adapter')
const cloudFoundryEnvironmentAdapter = require('./cloudfoundry-environment-adapter')

/**
 *
 */
class CloudFoundryCloudControllerAdapter extends HttpAdapter {

    constructor() {
        super()
        this._permissionsUrl = cloudFoundryEnvironmentAdapter.getPermissionsUrl()
        this._infoUrl = cloudFoundryEnvironmentAdapter.getCloudControllerInfoUrl()
        this._cachedTokenKeys = null
        this._cachedInfo = null
    }

    /**
     *
     * @returns {Promise<Object>} a promise, that is resolved with keys, which are used to sign bearer tokens
     */
    fetchTokenKeys() {
        if (this._cachedTokenKeys) {
            return Promise.resolve(this._cachedTokenKeys)
        }

        return this.fetchTokenEndpoint()
            .then((result) => {
                return this._fetch(result + '/token_keys')
            })
            .then((result) => {
                log('fetchTokenKeys cloudController tokenEndpoint result %j', result)
                const keys = result.keys.reduce((current, next) => (current[next.kid] = next, current), {})
                return this._cachedTokenKeys = keys
            })
            .catch((error) => {
                log('fetchTokenKeys err %s', error)
                Promise.reject(error)
            })
    }

    /**
     *
     * @return {Promise<String>} a promise, that is resolved with the url of the token endpoint
     */
    fetchTokenEndpoint() {
        return this.fetchInfo()
            .then((result) => {
                return result.token_endpoint
            })
    }

    /**
     *
     * @returns {Promise<Object>} a promise, that is resolved with cloud controller info
     */
    fetchInfo() {
        if (this._cachedInfo) {
            return Promise.resolve(this._cachedInfo)
        }

        return this._fetch(this._infoUrl, {}, {})
            .then((result) => {
                log('fetchTokenKeys cloudController info result %j', result)
                return this._cachedInfo = result
            })
    }

    /**
     *
     * @param {string} token the oauth token, that is used to lookup permissions
     * @returns {Promise<Object>} a promise, that is resolved with read permission info
     */
    fetchPermissions(token) {
        log('fetchPermissions cloudController %s for %s', this._permissionsUrl, token)
        return this._fetch(this._permissionsUrl, {
                "Authorization": "Bearer " + token
            }, {})
            .then((result) => {
                log('fetchPermissions result %j', result)
                return {
                    readSensitive: result.read_sensitive_data || false,
                    readBasic: result.read_basic_data || false
                }
            })
            .catch((error) => {
                log('fetchPermissions err %j', error)
                return Promise.reject(error)
            })
    }
}

module.exports = new CloudFoundryCloudControllerAdapter()<commit_msg>chore: add error handling and logging<commit_after>'use strict'

const log = require('util').debuglog('cloudfoundry-actuator-middleware');

const HttpAdapter = require('./http-adapter')
const cloudFoundryEnvironmentAdapter = require('./cloudfoundry-environment-adapter')

/**
 *
 */
class CloudFoundryCloudControllerAdapter extends HttpAdapter {

    constructor() {
        super()
        this._permissionsUrl = cloudFoundryEnvironmentAdapter.getPermissionsUrl()
        this._infoUrl = cloudFoundryEnvironmentAdapter.getCloudControllerInfoUrl()
        this._cachedTokenKeys = null
        this._cachedInfo = null
    }

    /**
     *
     * @returns {Promise<Object>} a promise, that is resolved with keys, which are used to sign bearer tokens
     */
    fetchTokenKeys() {
        if (this._cachedTokenKeys) {
            return Promise.resolve(this._cachedTokenKeys)
        }

        return this.fetchTokenEndpoint()
            .then((result) => {
                log('fetchTokenKeys cloudController tokenEndpoint %j', result)
                return this._fetch(result + '/token_keys')
            })
            .then((result) => {
                log('fetchTokenKeys cloudController tokenEndpoint result %j', result)
                const keys = result.keys.reduce((current, next) => (current[next.kid] = next, current), {})
                return this._cachedTokenKeys = keys
            })
            .catch((error) => {
                log('fetchTokenKeys err %j', error)
                Promise.reject(error)
            })
    }

    /**
     *
     * @return {Promise<String>} a promise, that is resolved with the url of the token endpoint
     */
    fetchTokenEndpoint() {
        return this.fetchInfo()
            .then((result) => {
                log('fetchTokenEndpoint cloudController result %j', result)
                return result.token_endpoint
            })
            .catch((e) => {
                log('fetchTokenEndpoint cloudController err %j', e)
                return Promise.reject(e)
            })
    }

    /**
     *
     * @returns {Promise<Object>} a promise, that is resolved with cloud controller info
     */
    fetchInfo() {
        if (this._cachedInfo) {
            return Promise.resolve(this._cachedInfo)
        }

        return this._fetch(this._infoUrl, {}, {})
            .then((result) => {
                log('fetchTokenKeys cloudController info result %j', result)
                return this._cachedInfo = result
            })
            .catch((e) => {
                log('fetchTokenEndpoint cloudController info err %j', e)
                return Promise.reject(e)
            })
    }

    /**
     *
     * @param {string} token the oauth token, that is used to lookup permissions
     * @returns {Promise<Object>} a promise, that is resolved with read permission info
     */
    fetchPermissions(token) {
        log('fetchPermissions cloudController %s for %s', this._permissionsUrl, token)
        return this._fetch(this._permissionsUrl, {
                "Authorization": "Bearer " + token
            }, {})
            .then((result) => {
                log('fetchPermissions cloudController result %j', result)
                return {
                    readSensitive: result.read_sensitive_data || false,
                    readBasic: result.read_basic_data || false
                }
            })
            .catch((error) => {
                log('fetchPermissions cloudController err %j', error)
                return Promise.reject(error)
            })
    }
}

module.exports = new CloudFoundryCloudControllerAdapter()<|endoftext|>


<commit_before>function showsServerCpu(serverCpuSystem, serverCpuUser, serverCpuIoWait, serverCpuSteal, startTime) {
    var serverCpuSystemArr = [];
    var serverCpuUserArr = [];
    var serverCpuIoWaitArr = [];
    var serverCpuStealArr = [];

    var history_cpuUser = null;

    zbxApi.getHistory.get(serverCpuSystem.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverCpuSystemArr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuUser.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        history_cpuUser = zbxApi.getHistory.success(data);
        $.each(history_cpuUser.result, function(k, v) {
            serverCpuUserArr[k] = [];
            serverCpuUserArr[k][0] = parseInt(v.clock) * 1000;
            serverCpuUserArr[k][1] = parseFloat(v.value);
        });
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuIoWait.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        serverCpuIoWaitArr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuSteal.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        serverCpuStealArr = zbxApi.getHistory.success(data);

        var chartId = "cpuUse";
        var title = 'CPU 사용량';
        var series = [{
            name: 'CPU System',
            data: serverCpuSystemArr
        }, {
            name: 'CPU User',
            data: serverCpuUserArr
        }, {
            name: 'CPU IoWait',
            data: serverCpuIoWaitArr
        }, {
            name: 'CPU Steal',
            data: serverCpuStealArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    });

    /*exporting: {
     buttons: {
     contextButton: {
     enabled: false
     },
     exportButton: {
     text: 'Download',
     // Use only the download related menu items from the default context button
     menuItems: Highcharts.getOptions().exporting.buttons.contextButton.menuItems.splice(2)
     },
     printButton: {
     text: 'Print',
     onclick: function () {
     this.print();
     }
     }
     }
     }*/
    /*$("#exporting").click(function () {
     console.log("Click exporting Button");
     Highcharts.getOptions().exporting.buttons.contextButton.menuItems
     })*/
}

function showServerMemory(serverMemoryUse, startTime) {
    var serverMemoryUseArr = [];

    zbxApi.getHistory.get(serverMemoryUse.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverMemoryUseArr = zbxApi.getHistory.success(data);

        var chartId = "memoryAll";
        var title = '전체메모리';
        var series = [{
            name: 'Memory Use',
            data: serverMemoryUseArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    })
}

function showServerTraffic(serverTraInEth0, serverTraOutEth0, serverTraTotalEth0, startTime) {
    var serverTraInEth0Arr = [];
    var serverTraOutEth0Arr = [];
    var serverTraTotEth0Arr = [];

    zbxApi.getHistory.get(serverTraInEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT).then(function(data) {
        serverTraInEth0Arr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverTraOutEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT);
    }).then(function(data) {
        serverTraOutEth0Arr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverTraTotalEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT);
    }).then(function(data) {
        serverTraTotEth0Arr = zbxApi.getHistory.success(data);

        $(function() {
            Highcharts.chart('trafficUse', {
                chart: {
                    backgroundColor: '#424973',
                    zoomType: 'x',
                    height: 200,
                    spacingTop: 10,
                    spacingBottom: 0,
                    spacingLeft: 0,
                    spacingRight: 0
                },
                title: {
                    text: '',
                },
                subtitle: {
                    text: ''
                },
                xAxis: {
                    gridLineColor: '#707073',
                    lineColor: '#707073',
                    minorGridLineColor: '#505053',
                    tickColor: '#707073',
                    labels: {
                        style:{
                            color: '#E0E0E3'
                        },
                        formatter: function() {
                            var d2 = new Date(this.value);
                            var hours = "" + d2.getHours();
                            var minutes = "" + d2.getMinutes();
                            var seconds = "" + d2.getSeconds();
                            if (hours.length == 1) {
                                hours = "0" + hours;
                            }
                            if (minutes.length == 1) {
                                minutes = "0" + minutes;
                            }
                            if (seconds.length == 1) {
                                seconds = "0" + seconds;
                            }
                            return hours + ":" + minutes + ":" + seconds;
                        }
                    }
                },
                yAxis: {
                    gridLineColor: '#707073',
                    lineColor: '#707073',
                    minorGridLineColor: '#505053',
                    tickColor: '#707073',
                    labels: {
                        style:{
                            color: '#E0E0E3'
                        },
                        formatter: function() {
                            return Math.floor(this.value / 1000) +'Kbps';
                        }
                    }
                },
                tooltip: {
                    backgroundColor: 'rgba(0, 0, 0, 0.85)',
                    style: {
                        color: '#F0F0F0'
                    },
                    shared: true,
                    formatter: function () {
                        var d2 = new Date(this.x);
                        var hours = "" + d2.getHours();
                        var minutes = "" + d2.getMinutes();
                        var seconds = "" + d2.getSeconds();
                        if (hours.length == 1) {
                            hours = "0" + hours;
                        }
                        if (minutes.length == 1) {
                            minutes = "0" + minutes;
                        }
                        if (seconds.length == 1) {
                            seconds = "0" + seconds;
                        }

                        var s = [];
                        $.each(this.points, function (i, point) {
                            s += '
' + '' + point.series.name + '' + '
' + hours + ':' + minutes + ':' + seconds + '  ' + (point.y / 1000) + 'kbps';
                        });
                        return s;
                    }
                },
                plotOptions: {
                    series: {
                        stacking: 'normal',
                        marker: {
                            enabled: false //false
                        }
                    }
                },
                series: [{
                    name: 'Traffic In Eth0',
                    data: serverTraInEth0Arr,
                    color: '#FC4747'
                }, {
                    name: 'Traffic Out Eth0',
                    data: serverTraOutEth0Arr,
                    color: '#F2F234'
                }, {
                    name: 'Traffic Total Eth0',
                    data: serverTraTotEth0Arr,
                    color: '#FA60CE'
                }],
                legend: {
                    enabled: false
                },
                exporting: {
                    buttons: {
                        contextButton: {
                            enabled: false,
                            symbolStroke: 'transparent',
                            theme: {
                                fill:'#626992'
                            }
                        }
                    }
                }
            });
        });
    })
}

function serverOverViewInfo(serverTitle, serverIP, serverOS, serverName, serverAgentVersion) {
    $("#serverInfo").empty();

    var serverInfoTbl = '';
    serverInfoTbl += "
운영체제	" + serverOS + "
";
    serverInfoTbl += "
서버명	" + serverTitle + "
";
    serverInfoTbl += "
IP주소	" + serverIP + "
";
    serverInfoTbl += "
호스트명	" + serverName + "
";
    serverInfoTbl += "
에이전트	" + serverAgentVersion + "
";
    $("#serverInfo").append(serverInfoTbl);
}

function processView(hostid, startTime) {
    var lastProcessData = callApiForProcessTable(hostid);
    var processTbl = '';
    var MAX_PROCCOUNT = 7;
    var tableDataObj = {};
    var tableDataArr = [];

    var topProcessLastClock = parseInt(lastProcessData.lastclock) * 1000;
    var d2 = new Date(topProcessLastClock);
    var topProcessLastTime = d2.getFullYear() + "-" + d2.getMonth() + 1 + "-" + d2.getDate() + " " + d2.getHours() + ":" + d2.getMinutes();
    var sortProcessForTable = sortProcess(lastProcessData, "CPU");

    processTbl += "
";

    $.each(sortProcessForTable, function(k, v) {
        tableDataObj = {};

        tableDataObj.procName = v.procName;
        tableDataObj.cpuValue = parseFloat(v.totalCpuVal.toFixed(1));
        tableDataObj.memValue = parseFloat(v.totalMemVal.toFixed(1));
        tableDataObj.procCnt = parseInt(v.procCnt);
        tableDataArr.push(tableDataObj);
        if (k < MAX_PROCCOUNT) {
            var procCpuValue = v.totalCpuVal.toFixed(1);
            var procMemValue = v.totalMemVal.toFixed(1);

            processTbl += "
";
            processTbl += "" + v.procName + "	";
            processTbl += "" + v.procCnt + "	";
            processTbl += "" + procCpuValue + "	";
            processTbl += "" + procMemValue + "MB	";
            processTbl += "
";
        }
    });

    processTbl += "
";

    $("#processTime").text(topProcessLastTime);
    $("#serverProcessList").empty();
    $("#serverProcessList").append(processTbl);

    //화면 이동
    $("#processDetail_").click(function () {
        console.log("IN function processDetail_");
        console.log(hostid + " / " + startTime);
        $("#process_" + hostid).click();
    });
}

function showServerDisk(serverDiskUseRoot, startTime) {
    var serverDiskUseRootArr = [];

    zbxApi.getHistory.get(serverDiskUseRoot.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverDiskUseRootArr = zbxApi.getHistory.success(data);

        var chartId = "diskUse";
        var title = '디스크 사용량';
        var series = [{
            name: 'Disk Use : /',
            data: serverDiskUseRootArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    })
}

function EventListView(hostid) { //서버정보요약 - 이벤트목록
    var data_EventList = callApiForServerEvent(hostid);
    var eventTbl = '';

    eventTbl += "
";

    $.each(data_EventList, function(k, v) {
        var severity = convPriority(v.priority);
        var status = convStatus(v.value);
        var lastchange = convTime(v.lastchange);
        var age = convDeltaTime(v.lastchange);
        var ack = convAck(v.lastEvent.acknowledged);
        var host = v.hosts[0].host;
        var description = v.description;

        eventTbl += "
";
        if(severity == "information") {
            eventTbl += "" + severity + "	";
        } else if(severity == "warning") {
            eventTbl += "" + severity + "	";
        } else if(severity == "average") {
            eventTbl += "" + severity + "	";
        } else if(severity == "high") {
            eventTbl += "" + severity + "	";
        }

        if(status == "problem"){
            eventTbl += "" + status + "	";
        } else if(status == "OK"){
            eventTbl += "" + status + "	";
        }
        eventTbl += "" + lastchange + "	";
        eventTbl += "" + age + "	";
        eventTbl += "" + ack + "	";
        eventTbl += "" + host + "	";
        eventTbl += "" +
            "" +
            "" + description + "	";
        eventTbl += "
";
    });
    eventTbl += "
";
    $("#serverEventList").empty();
    $("#serverEventList").append(eventTbl);
}
<commit_msg>2017.03.20<commit_after>function showsServerCpu(serverCpuSystem, serverCpuUser, serverCpuIoWait, serverCpuSteal, startTime) {
    var serverCpuSystemArr = [];
    var serverCpuUserArr = [];
    var serverCpuIoWaitArr = [];
    var serverCpuStealArr = [];

    var history_cpuUser = null;

    zbxApi.getHistory.get(serverCpuSystem.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverCpuSystemArr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuUser.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        history_cpuUser = zbxApi.getHistory.success(data);
        $.each(history_cpuUser.result, function(k, v) {
            serverCpuUserArr[k] = [];
            serverCpuUserArr[k][0] = parseInt(v.clock) * 1000;
            serverCpuUserArr[k][1] = parseFloat(v.value);
        });
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuIoWait.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        serverCpuIoWaitArr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverCpuSteal.result[0].itemid, startTime, HISTORY_TYPE.FLOAT);
    }).then(function(data) {
        serverCpuStealArr = zbxApi.getHistory.success(data);

        var chartId = "cpuUse";
        var title = 'CPU 사용량';
        var series = [{
            name: 'CPU System',
            data: serverCpuSystemArr
        }, {
            name: 'CPU User',
            data: serverCpuUserArr
        }, {
            name: 'CPU IoWait',
            data: serverCpuIoWaitArr
        }, {
            name: 'CPU Steal',
            data: serverCpuStealArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    });

    /*exporting: {
     buttons: {
     contextButton: {
     enabled: false
     },
     exportButton: {
     text: 'Download',
     // Use only the download related menu items from the default context button
     menuItems: Highcharts.getOptions().exporting.buttons.contextButton.menuItems.splice(2)
     },
     printButton: {
     text: 'Print',
     onclick: function () {
     this.print();
     }
     }
     }
     }*/
    /*$("#exporting").click(function () {
     console.log("Click exporting Button");
     Highcharts.getOptions().exporting.buttons.contextButton.menuItems
     })*/
}

function showServerMemory(serverMemoryUse, startTime) {
    var serverMemoryUseArr = [];

    zbxApi.getHistory.get(serverMemoryUse.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverMemoryUseArr = zbxApi.getHistory.success(data);

        var chartId = "memoryAll";
        var title = '전체메모리';
        var series = [{
            name: 'Memory Use',
            data: serverMemoryUseArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    })
}

function showServerTraffic(serverTraInEth0, serverTraOutEth0, serverTraTotalEth0, startTime) {
    var serverTraInEth0Arr = [];
    var serverTraOutEth0Arr = [];
    var serverTraTotEth0Arr = [];

    zbxApi.getHistory.get(serverTraInEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT).then(function(data) {
        serverTraInEth0Arr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverTraOutEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT);
    }).then(function(data) {
        serverTraOutEth0Arr = zbxApi.getHistory.success(data);
    }).then(function() {
        return zbxApi.getHistory.get(serverTraTotalEth0.result[0].itemid, startTime, HISTORY_TYPE.UNSIGNEDINT);
    }).then(function(data) {
        serverTraTotEth0Arr = zbxApi.getHistory.success(data);

        $(function() {
            Highcharts.chart('trafficUse', {
                chart: {
                    backgroundColor: '#424973',
                    zoomType: 'x',
                    height: 200,
                    spacingTop: 10,
                    spacingBottom: 0,
                    spacingLeft: 0,
                    spacingRight: 0
                },
                title: {
                    text: '',
                },
                subtitle: {
                    text: ''
                },
                xAxis: {
                    gridLineColor: '#707073',
                    lineColor: '#707073',
                    minorGridLineColor: '#505053',
                    tickColor: '#707073',
                    labels: {
                        style:{
                            color: '#E0E0E3'
                        },
                        formatter: function() {
                            var d2 = new Date(this.value);
                            var hours = "" + d2.getHours();
                            var minutes = "" + d2.getMinutes();
                            var seconds = "" + d2.getSeconds();
                            if (hours.length == 1) {
                                hours = "0" + hours;
                            }
                            if (minutes.length == 1) {
                                minutes = "0" + minutes;
                            }
                            if (seconds.length == 1) {
                                seconds = "0" + seconds;
                            }
                            return hours + ":" + minutes + ":" + seconds;
                        }
                    }
                },
                yAxis: {
                    gridLineColor: '#707073',
                    lineColor: '#707073',
                    minorGridLineColor: '#505053',
                    tickColor: '#707073',
                    labels: {
                        style:{
                            color: '#E0E0E3'
                        },
                        formatter: function() {
                            return Math.floor(this.value / 1000) +'Kbps';
                        }
                    }
                },
                tooltip: {
                    backgroundColor: 'rgba(0, 0, 0, 0.85)',
                    style: {
                        color: '#F0F0F0'
                    },
                    shared: true,
                    formatter: function () {
                        var d2 = new Date(this.x);
                        var hours = "" + d2.getHours();
                        var minutes = "" + d2.getMinutes();
                        var seconds = "" + d2.getSeconds();
                        if (hours.length == 1) {
                            hours = "0" + hours;
                        }
                        if (minutes.length == 1) {
                            minutes = "0" + minutes;
                        }
                        if (seconds.length == 1) {
                            seconds = "0" + seconds;
                        }

                        var s = [];
                        $.each(this.points, function (i, point) {
                            s += '
' + '' + point.series.name + '' + '
' + hours + ':' + minutes + ':' + seconds + '  ' + (point.y / 1000) + 'kbps';
                        });
                        return s;
                    }
                },
                plotOptions: {
                    series: {
                        stacking: 'normal',
                        marker: {
                            enabled: false //false
                        }
                    }
                },
                series: [{
                    name: 'Traffic In Eth0',
                    data: serverTraInEth0Arr,
                    color: '#FC4747'
                }, {
                    name: 'Traffic Out Eth0',
                    data: serverTraOutEth0Arr,
                    color: '#F2F234'
                }, {
                    name: 'Traffic Total Eth0',
                    data: serverTraTotEth0Arr,
                    color: '#FA60CE'
                }],
                legend: {
                    enabled: false
                },
                exporting: {
                    buttons: {
                        contextButton: {
                            enabled: false,
                            symbolStroke: 'transparent',
                            theme: {
                                fill:'#626992'
                            }
                        }
                    }
                }
            });
        });
    })
}

function serverOverViewInfo(serverTitle, serverIP, serverOS, serverName, serverAgentVersion) {
    $("#serverInfo").empty();

    var serverInfoTbl = '';
    serverInfoTbl += "
운영체제	" + serverOS + "
";
    serverInfoTbl += "
서버명	" + serverTitle + "
";
    serverInfoTbl += "
IP주소	" + serverIP + "
";
    serverInfoTbl += "
호스트명	" + serverName + "
";
    serverInfoTbl += "
에이전트	" + serverAgentVersion + "
";
    $("#serverInfo").append(serverInfoTbl);
}

function processView(hostid, startTime) {
    var lastProcessData = callApiForProcessTable(hostid);
    var processTbl = '';
    var MAX_PROCCOUNT = 7;
    var tableDataObj = {};
    var tableDataArr = [];

    var topProcessLastClock = parseInt(lastProcessData.lastclock) * 1000;
    var d2 = new Date(topProcessLastClock);
    var topProcessLastTime = d2.getFullYear() + "-" + d2.getMonth() + 1 + "-" + d2.getDate() + " " + d2.getHours() + ":" + d2.getMinutes();
    var sortProcessForTable = sortProcess(lastProcessData, "CPU");

    processTbl += "
";

    $.each(sortProcessForTable, function(k, v) {
        tableDataObj = {};

        tableDataObj.procName = v.procName;
        tableDataObj.cpuValue = parseFloat(v.totalCpuVal.toFixed(1));
        tableDataObj.memValue = parseFloat(v.totalMemVal.toFixed(1));
        tableDataObj.procCnt = parseInt(v.procCnt);
        tableDataArr.push(tableDataObj);
        if (k < MAX_PROCCOUNT) {
            var procCpuValue = v.totalCpuVal.toFixed(1);
            var procMemValue = v.totalMemVal.toFixed(1);

            processTbl += "
";
            processTbl += "" + v.procName + "	";
            processTbl += "" + v.procCnt + "	";
            processTbl += "" + procCpuValue + "	";
            processTbl += "" + procMemValue + "MB	";
            processTbl += "
";
        }
    });

    processTbl += "
";

    $("#processTime").text(topProcessLastTime);
    $("#serverProcessList").empty();
    $("#serverProcessList").append(processTbl);

    //화면 이동
    $("#processDetail_").click(function () {
        console.log("IN function processDetail_");
        console.log(hostid + " / " + startTime);
        $("#process_" + hostid).click();
    });
}

function showServerDisk(serverDiskUseRoot, startTime) {
    var serverDiskUseRootArr = [];

    zbxApi.getHistory.get(serverDiskUseRoot.result[0].itemid, startTime, HISTORY_TYPE.FLOAT).then(function(data) {
        serverDiskUseRootArr = zbxApi.getHistory.success(data);

        var chartId = "diskUse";
        var title = '디스크 사용량';
        var series = [{
            name: 'Disk Use : /',
            data: serverDiskUseRootArr
        }];
        var enable = false;
        chartCall(chartId, title, series, Label.percent, enable);
    })
}

function EventListView(hostid) { //서버정보요약 - 이벤트목록
    var data_EventList = callApiForServerEvent(hostid);
    var eventTbl = '';

    eventTbl += "
";

    $.each(data_EventList, function(k, v) {
        var severity = convPriority(v.priority);
        var status = convStatus(v.value);
        var lastchange = convTime(v.lastchange);
        var age = convDeltaTime(v.lastchange);
        var ack = convAck(v.lastEvent.acknowledged);
        var host = v.hosts[0].host;
        var description = v.description;

        eventTbl += "
";
        if(severity == "information") {
            eventTbl += "" + severity + "	";
        } else if(severity == "warning") {
            eventTbl += "" + severity + "	";
        } else if(severity == "average") {
            eventTbl += "" + severity + "	";
        } else if(severity == "high") {
            eventTbl += "" + severity + "	";
        }

        if(status == "problem"){
            eventTbl += "" + status + "	";
        } else if(status == "OK"){
            eventTbl += "" + status + "	";
        }
        eventTbl += "" + lastchange + "	";
        eventTbl += "" + age + "	";
        if(ack == "Unacked"){
            eventTbl += "" + ack + "	";
        } else if(ack = "Acked"){
            eventTbl += "" + ack + "	";
        }
        eventTbl += "" + host + "	";
        eventTbl += "" +
            "" +
            "" + description + "	";
        eventTbl += "
";
    });
    eventTbl += "
";
    $("#serverEventList").empty();
    $("#serverEventList").append(eventTbl);
}
<|endoftext|>


<commit_before>// ==========================================================================
// Project:  SproutCore Runtime
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2010 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals sc_assert */

require('sproutcore-runtime/system/object');

// ..........................................................
// HELPERS
//

var slice = Array.prototype.slice;

// invokes passed params - normalizing so you can pass target/func,
// target/string or just func
function invoke(target, method, args, ignore) {

  if (method===undefined) {
    method = target;
    target = undefined;
  }

  if ('string'===typeof method) method = target[method];
  if (args && ignore>0) {
    args = args.length>ignore ? slice.call(args, ignore) : null;
  }
  // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
  return method.apply(target || this, args || []);
}

// ..........................................................
// RUNLOOP
//

var timerMark; // used by timers...

var RunLoop = SC.Object.extend({

  _prev: null,

  init: function(prev) {
    this._prev = prev;
    this.onceTimers = {};
  },

  end: function() {
    this.flush();
    return this._prev;
  },

  // ..........................................................
  // Delayed Actions
  //

  schedule: function(queueName, target, method) {
    var queues = this._queues, queue;
    if (!queues) queues = this._queues = {};
    queue = queues[queueName];
    if (!queue) queue = queues[queueName] = [];

    var args = arguments.length>3 ? slice.call(arguments, 3) : null;
    queue.push({ target: target, method: method, args: args });
    return this;
  },

  flush: function(queueName) {
    var queues = this._queues, queueNames, idx, len, queue, log;

    if (!queues) return this; // nothing to do

    function iter(item) {
      invoke(item.target, item.method, item.args);
    }

    SC.watch.flushPending(); // make sure all chained watchers are setup

    if (queueName) {
      while (this._queues && (queue = this._queues[queueName])) {
        this._queues[queueName] = null;

        //@if (debug)
        log = SC.LOG_BINDINGS && queueName==='sync';
        if (log) SC.Logger.log('Begin: Flush Sync Queue');
        //@endif

        // the sync phase is to allow property changes to propogate.  don't
        // invoke observers until that is finished.
        if (queueName === 'sync') SC.beginPropertyChanges();
        queue.forEach(iter);
        if (queueName === 'sync') SC.endPropertyChanges();

        //@if (debug)
        if (log) SC.Logger.log('End: Flush Sync Queue');
        //@endif

      }

    } else {
      queueNames = SC.run.queues;
      len = queueNames.length;
      do {
        this._queues = null;
        for(idx=0;idx<len;idx++) {
          queueName = queueNames[idx];
          queue = queues[queueName];

          //@if (debug)
          log = SC.LOG_BINDINGS && queueName==='sync';
          if (log) SC.Logger.log('Begin: Flush Sync Queue');
          //@endif

          if (queueName === 'sync') SC.beginPropertyChanges();
          if (queue) queue.forEach(iter);
          if (queueName === 'sync') SC.endPropertyChanges();

          //@if (debug)
          if (log) SC.Logger.log('End: Flush Sync Queue');
          //@endif

        }

      } while (queues = this._queues); // go until queues stay clean
    }

    timerMark = null;

    return this;
  }

});

SC.RunLoop = RunLoop;

// ..........................................................
// SC.run - this is ideally the only public API the dev sees
//

var run;

/**
  Runs the passed target and method inside of a runloop, ensuring any
  deferred actions including bindings and views updates are flushed at the
  end.

  Normally you should not need to invoke this method yourself.  However if
  you are implementing raw event handlers when interfacing with other
  libraries or plugins, you should probably wrap all of your code inside this
  call.

  @function
  @param {Object} target
    (Optional) target of method to call

  @param {Function|String} method
    Method to invoke.  May be a function or a string.  If you pass a string
    then it will be looked up on the passed target.

  @param {Object...} args
    Any additional arguments you wish to pass to the method.

  @returns {Object} return value from invoking the passed function.
*/
SC.run = run = function(target, method) {

  var ret, loop;
  run.begin();
  if (target || method) ret = invoke(target, method);
  run.end();
  return ret;
};

/**
  Begins a new RunLoop.  Any deferred actions invoked after the begin will
  be buffered until you invoke a matching call to SC.run.end().  This is
  an lower-level way to use a RunLoop instead of using SC.run().

  @returns {void}
*/
SC.run.begin = function() {
  run.currentRunLoop = new RunLoop(run.currentRunLoop);
};

/**
  Ends a RunLoop.  This must be called sometime after you call SC.run.begin()
  to flush any deferred actions.  This is a lower-level way to use a RunLoop
  instead of using SC.run().

  @returns {void}
*/
SC.run.end = function() {
  sc_assert('must have a current run loop', run.currentRunLoop);
  run.currentRunLoop = run.currentRunLoop.end();
};

/**
  Array of named queues.  This array determines the order in which queues
  are flushed at the end of the RunLoop.  You can define your own queues by
  simply adding the queue name to this array.  Normally you should not need
  to inspect or modify this property.

  @property {String}
*/
SC.run.queues = ['sync', 'actions', 'timers'];

/**
  Adds the passed target/method and any optional arguments to the named
  queue to be executed at the end of the RunLoop.  If you have not already
  started a RunLoop when calling this method one will be started for you
  automatically.

  At the end of a RunLoop, any methods scheduled in this way will be invoked.
  Methods will be invoked in an order matching the named queues defined in
  the run.queues property.

  @param {String} queue
    The name of the queue to schedule against.  Default queues are 'sync' and
    'actions'

  @param {Object} target
    (Optional) target object to use as the context when invoking a method.

  @param {String|Function} method
    The method to invoke.  If you pass a string it will be resolved on the
    target object at the time the scheduled item is invoked allowing you to
    change the target function.

  @param {Object} arguments...
    Optional arguments to be passed to the queued method.

  @returns {void}
*/
SC.run.schedule = function(queue, target, method) {
  var loop = run.autorun();
  loop.schedule.apply(loop, arguments);
};

var autorunTimer;

function autorun() {
  autorunTimer = null;
  if (run.currentRunLoop) run.end();
}

/**
  Begins a new RunLoop is necessary and schedules a timer to flush the
  RunLoop at a later time.  This method is used by parts of SproutCore to
  ensure the RunLoop always finishes.  You normally do not need to call this
  method directly.  Instead use SC.run().

  @returns {SC.RunLoop} the new current RunLoop
*/
SC.run.autorun = function() {

  if (!run.currentRunLoop) {
    run.begin();
    // TODO: throw during tests
    if (!autorunTimer) {
      autorunTimer = setTimeout(autorun, 1);
    }
  }

  return run.currentRunLoop;
};

/**
  Immediately flushes any events scheduled in the 'sync' queue.  Bindings
  use this queue so this method is a useful way to immediately force all
  bindings in the application to sync.

  You should call this method anytime you need any changed state to propogate
  throughout the app immediately without repainting the UI.

  @returns {void}
*/
SC.run.sync = function() {
  run.autorun();
  run.currentRunLoop.flush('sync');
};

// ..........................................................
// TIMERS
//

var timers = {}; // active timers...

var laterScheduled = false;
function invokeLaterTimers() {
  var now = (+ new Date()), earliest = -1;
  for(var key in timers) {
    if (!timers.hasOwnProperty(key)) continue;
    var timer = timers[key];
    if (timer && timer.expires) {
      if (now >= timer.expires) {
        delete timers[key];
        invoke(timer.target, timer.method, timer.args, 2);
      } else {
        if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
      }
    }
  }

  // schedule next timeout to fire...
  if (earliest>0) setTimeout(invokeLaterTimers, earliest-(+ new Date()));
}

/**
  Invokes the passed target/method and optional arguments after a specified
  period if time.  The last parameter of this method must always be a number
  of milliseconds.

  You should use this method whenever you need to run some action after a
  period of time inside of using setTimeout().  This method will ensure that
  items that expire during the same script execution cycle all execute
  together, which is often more efficient than using a real setTimeout.

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @param {Number} wait
    Number of milliseconds to wait.

  @returns {Timer} an object you can use to cancel a timer at a later time.
*/
SC.run.later = function(target, method) {
  var args, expires, timer, guid, wait;

  // setTimeout compatibility...
  if (arguments.length===2 && 'function' === typeof target) {
    wait   = method;
    method = target;
    target = undefined;
    args   = [target, method];

  } else {
    args = slice.call(arguments);
    wait = args.pop();
  }

  expires = (+ new Date())+wait;
  timer   = { target: target, method: method, expires: expires, args: args };
  guid    = SC.guidFor(timer);
  timers[guid] = timer;
  run.once(timers, invokeLaterTimers);
  return guid;
};

function invokeOnceTimer(guid, onceTimers) {
  if (onceTimers[this.tguid]) delete onceTimers[this.tguid][this.mguid];
  if (timers[guid]) invoke(this.target, this.method, this.args, 2);
  delete timers[guid];
}

/**
  Schedules an item to run one time during the current RunLoop.  Calling
  this method with the same target/method combination will have no effect.

  Note that although you can pass optional arguments these will not be
  considered when looking for duplicates.  New arguments will replace previous
  calls.

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @returns {Object} timer
*/
SC.run.once = function(target, method) {
  var tguid = SC.guidFor(target), mguid = SC.guidFor(method), guid, timer;

  var onceTimers = run.autorun().onceTimers;
  guid = onceTimers[tguid] && onceTimers[tguid][mguid];
  if (guid && timers[guid]) {
    timers[guid].args = slice.call(arguments); // replace args

  } else {
    timer = {
      target: target,
      method: method,
      args:   slice.call(arguments),
      tguid:  tguid,
      mguid:  mguid
    };

    guid  = SC.guidFor(timer);
    timers[guid] = timer;
    if (!onceTimers[tguid]) onceTimers[tguid] = {};
    onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once

    run.schedule('timers', timer, invokeOnceTimer, guid, onceTimers);
  }

  return guid;
};

var scheduledNext = false;
function invokeNextTimers() {
  scheduledNext = null;
  for(var key in timers) {
    if (!timers.hasOwnProperty(key)) continue;
    var timer = timers[key];
    if (timer.next) {
      delete timers[key];
      invoke(timer.target, timer.method, timer.args, 2);
    }
  }
}

/**
  Schedules an item to run after control has been returned to the system.
  This is often equivalent to calling setTimeout(function...,1).

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @returns {Object} timer
*/
SC.run.next = function(target, method) {
  var timer, guid;

  timer = {
    target: target,
    method: method,
    args: slice.call(arguments),
    next: true
  };

  guid = SC.guidFor(timer);
  timers[guid] = timer;

  if (!scheduledNext) scheduledNext = setTimeout(invokeNextTimers, 1);
  return guid;
};

/**
  Cancels a scheduled item.  Must be a value returned by `SC.run.later()`,
  `SC.run.once()`, or `SC.run.next()`.

  @param {Object} timer
    Timer object to cancel

  @returns {void}
*/
SC.run.cancel = function(timer) {
  delete timers[timer];
};

// ..........................................................
// DEPRECATED API
//

/**
  @deprecated
  @method

  Use `#js:SC.run.begin()` instead
*/
SC.RunLoop.begin = SC.run.begin;

/**
  @deprecated
  @method

  Use `#js:SC.run.end()` instead
*/
SC.RunLoop.end = SC.run.end;

<commit_msg>In testing mode, run autoruns synchronously, don't schedule them<commit_after>// ==========================================================================
// Project:  SproutCore Runtime
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2010 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================
/*globals sc_assert */

require('sproutcore-runtime/system/object');

// ..........................................................
// HELPERS
//

var slice = Array.prototype.slice;

// invokes passed params - normalizing so you can pass target/func,
// target/string or just func
function invoke(target, method, args, ignore) {

  if (method===undefined) {
    method = target;
    target = undefined;
  }

  if ('string'===typeof method) method = target[method];
  if (args && ignore>0) {
    args = args.length>ignore ? slice.call(args, ignore) : null;
  }
  // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
  return method.apply(target || this, args || []);
}

// ..........................................................
// RUNLOOP
//

var timerMark; // used by timers...

var RunLoop = SC.Object.extend({

  _prev: null,

  init: function(prev) {
    this._prev = prev;
    this.onceTimers = {};
  },

  end: function() {
    this.flush();
    return this._prev;
  },

  // ..........................................................
  // Delayed Actions
  //

  schedule: function(queueName, target, method) {
    var queues = this._queues, queue;
    if (!queues) queues = this._queues = {};
    queue = queues[queueName];
    if (!queue) queue = queues[queueName] = [];

    var args = arguments.length>3 ? slice.call(arguments, 3) : null;
    queue.push({ target: target, method: method, args: args });
    return this;
  },

  flush: function(queueName) {
    var queues = this._queues, queueNames, idx, len, queue, log;

    if (!queues) return this; // nothing to do

    function iter(item) {
      invoke(item.target, item.method, item.args);
    }

    SC.watch.flushPending(); // make sure all chained watchers are setup

    if (queueName) {
      while (this._queues && (queue = this._queues[queueName])) {
        this._queues[queueName] = null;

        //@if (debug)
        log = SC.LOG_BINDINGS && queueName==='sync';
        if (log) SC.Logger.log('Begin: Flush Sync Queue');
        //@endif

        // the sync phase is to allow property changes to propogate.  don't
        // invoke observers until that is finished.
        if (queueName === 'sync') SC.beginPropertyChanges();
        queue.forEach(iter);
        if (queueName === 'sync') SC.endPropertyChanges();

        //@if (debug)
        if (log) SC.Logger.log('End: Flush Sync Queue');
        //@endif

      }

    } else {
      queueNames = SC.run.queues;
      len = queueNames.length;
      do {
        this._queues = null;
        for(idx=0;idx<len;idx++) {
          queueName = queueNames[idx];
          queue = queues[queueName];

          //@if (debug)
          log = SC.LOG_BINDINGS && queueName==='sync';
          if (log) SC.Logger.log('Begin: Flush Sync Queue');
          //@endif

          if (queueName === 'sync') SC.beginPropertyChanges();
          if (queue) queue.forEach(iter);
          if (queueName === 'sync') SC.endPropertyChanges();

          //@if (debug)
          if (log) SC.Logger.log('End: Flush Sync Queue');
          //@endif

        }

      } while (queues = this._queues); // go until queues stay clean
    }

    timerMark = null;

    return this;
  }

});

SC.RunLoop = RunLoop;

// ..........................................................
// SC.run - this is ideally the only public API the dev sees
//

var run;

/**
  Runs the passed target and method inside of a runloop, ensuring any
  deferred actions including bindings and views updates are flushed at the
  end.

  Normally you should not need to invoke this method yourself.  However if
  you are implementing raw event handlers when interfacing with other
  libraries or plugins, you should probably wrap all of your code inside this
  call.

  @function
  @param {Object} target
    (Optional) target of method to call

  @param {Function|String} method
    Method to invoke.  May be a function or a string.  If you pass a string
    then it will be looked up on the passed target.

  @param {Object...} args
    Any additional arguments you wish to pass to the method.

  @returns {Object} return value from invoking the passed function.
*/
SC.run = run = function(target, method) {

  var ret, loop;
  run.begin();
  if (target || method) ret = invoke(target, method);
  run.end();
  return ret;
};

/**
  Begins a new RunLoop.  Any deferred actions invoked after the begin will
  be buffered until you invoke a matching call to SC.run.end().  This is
  an lower-level way to use a RunLoop instead of using SC.run().

  @returns {void}
*/
SC.run.begin = function() {
  run.currentRunLoop = new RunLoop(run.currentRunLoop);
};

/**
  Ends a RunLoop.  This must be called sometime after you call SC.run.begin()
  to flush any deferred actions.  This is a lower-level way to use a RunLoop
  instead of using SC.run().

  @returns {void}
*/
SC.run.end = function() {
  sc_assert('must have a current run loop', run.currentRunLoop);
  run.currentRunLoop = run.currentRunLoop.end();
};

/**
  Array of named queues.  This array determines the order in which queues
  are flushed at the end of the RunLoop.  You can define your own queues by
  simply adding the queue name to this array.  Normally you should not need
  to inspect or modify this property.

  @property {String}
*/
SC.run.queues = ['sync', 'actions', 'timers'];

/**
  Adds the passed target/method and any optional arguments to the named
  queue to be executed at the end of the RunLoop.  If you have not already
  started a RunLoop when calling this method one will be started for you
  automatically.

  At the end of a RunLoop, any methods scheduled in this way will be invoked.
  Methods will be invoked in an order matching the named queues defined in
  the run.queues property.

  @param {String} queue
    The name of the queue to schedule against.  Default queues are 'sync' and
    'actions'

  @param {Object} target
    (Optional) target object to use as the context when invoking a method.

  @param {String|Function} method
    The method to invoke.  If you pass a string it will be resolved on the
    target object at the time the scheduled item is invoked allowing you to
    change the target function.

  @param {Object} arguments...
    Optional arguments to be passed to the queued method.

  @returns {void}
*/
SC.run.schedule = function(queue, target, method) {
  var loop = run.autorun();
  loop.schedule.apply(loop, arguments);
};

var autorunTimer;

function autorun() {
  autorunTimer = null;
  if (run.currentRunLoop) run.end();
}

/**
  Begins a new RunLoop is necessary and schedules a timer to flush the
  RunLoop at a later time.  This method is used by parts of SproutCore to
  ensure the RunLoop always finishes.  You normally do not need to call this
  method directly.  Instead use SC.run().

  @returns {SC.RunLoop} the new current RunLoop
*/
SC.run.autorun = function() {

  if (!run.currentRunLoop) {
    run.begin();

    // TODO: throw during tests
    if (SC.testing) {
      run.end();
    } else if (!autorunTimer) {
      autorunTimer = setTimeout(autorun, 1);
    }
  }

  return run.currentRunLoop;
};

/**
  Immediately flushes any events scheduled in the 'sync' queue.  Bindings
  use this queue so this method is a useful way to immediately force all
  bindings in the application to sync.

  You should call this method anytime you need any changed state to propogate
  throughout the app immediately without repainting the UI.

  @returns {void}
*/
SC.run.sync = function() {
  run.autorun();
  run.currentRunLoop.flush('sync');
};

// ..........................................................
// TIMERS
//

var timers = {}; // active timers...

var laterScheduled = false;
function invokeLaterTimers() {
  var now = (+ new Date()), earliest = -1;
  for(var key in timers) {
    if (!timers.hasOwnProperty(key)) continue;
    var timer = timers[key];
    if (timer && timer.expires) {
      if (now >= timer.expires) {
        delete timers[key];
        invoke(timer.target, timer.method, timer.args, 2);
      } else {
        if (earliest<0 || (timer.expires < earliest)) earliest=timer.expires;
      }
    }
  }

  // schedule next timeout to fire...
  if (earliest>0) setTimeout(invokeLaterTimers, earliest-(+ new Date()));
}

/**
  Invokes the passed target/method and optional arguments after a specified
  period if time.  The last parameter of this method must always be a number
  of milliseconds.

  You should use this method whenever you need to run some action after a
  period of time inside of using setTimeout().  This method will ensure that
  items that expire during the same script execution cycle all execute
  together, which is often more efficient than using a real setTimeout.

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @param {Number} wait
    Number of milliseconds to wait.

  @returns {Timer} an object you can use to cancel a timer at a later time.
*/
SC.run.later = function(target, method) {
  var args, expires, timer, guid, wait;

  // setTimeout compatibility...
  if (arguments.length===2 && 'function' === typeof target) {
    wait   = method;
    method = target;
    target = undefined;
    args   = [target, method];

  } else {
    args = slice.call(arguments);
    wait = args.pop();
  }

  expires = (+ new Date())+wait;
  timer   = { target: target, method: method, expires: expires, args: args };
  guid    = SC.guidFor(timer);
  timers[guid] = timer;
  run.once(timers, invokeLaterTimers);
  return guid;
};

function invokeOnceTimer(guid, onceTimers) {
  if (onceTimers[this.tguid]) delete onceTimers[this.tguid][this.mguid];
  if (timers[guid]) invoke(this.target, this.method, this.args, 2);
  delete timers[guid];
}

/**
  Schedules an item to run one time during the current RunLoop.  Calling
  this method with the same target/method combination will have no effect.

  Note that although you can pass optional arguments these will not be
  considered when looking for duplicates.  New arguments will replace previous
  calls.

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @returns {Object} timer
*/
SC.run.once = function(target, method) {
  var tguid = SC.guidFor(target), mguid = SC.guidFor(method), guid, timer;

  var onceTimers = run.autorun().onceTimers;
  guid = onceTimers[tguid] && onceTimers[tguid][mguid];
  if (guid && timers[guid]) {
    timers[guid].args = slice.call(arguments); // replace args

  } else {
    timer = {
      target: target,
      method: method,
      args:   slice.call(arguments),
      tguid:  tguid,
      mguid:  mguid
    };

    guid  = SC.guidFor(timer);
    timers[guid] = timer;
    if (!onceTimers[tguid]) onceTimers[tguid] = {};
    onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once

    run.schedule('timers', timer, invokeOnceTimer, guid, onceTimers);
  }

  return guid;
};

var scheduledNext = false;
function invokeNextTimers() {
  scheduledNext = null;
  for(var key in timers) {
    if (!timers.hasOwnProperty(key)) continue;
    var timer = timers[key];
    if (timer.next) {
      delete timers[key];
      invoke(timer.target, timer.method, timer.args, 2);
    }
  }
}

/**
  Schedules an item to run after control has been returned to the system.
  This is often equivalent to calling setTimeout(function...,1).

  @param {Object} target
    (optional) target of method to invoke

  @param {Function|String} method
    The method to invoke.  If you pass a string it will be resolved on the
    target at the time the method is invoked.

  @param {Object...} args
    Optional arguments to pass to the timeout.

  @returns {Object} timer
*/
SC.run.next = function(target, method) {
  var timer, guid;

  timer = {
    target: target,
    method: method,
    args: slice.call(arguments),
    next: true
  };

  guid = SC.guidFor(timer);
  timers[guid] = timer;

  if (!scheduledNext) scheduledNext = setTimeout(invokeNextTimers, 1);
  return guid;
};

/**
  Cancels a scheduled item.  Must be a value returned by `SC.run.later()`,
  `SC.run.once()`, or `SC.run.next()`.

  @param {Object} timer
    Timer object to cancel

  @returns {void}
*/
SC.run.cancel = function(timer) {
  delete timers[timer];
};

// ..........................................................
// DEPRECATED API
//

/**
  @deprecated
  @method

  Use `#js:SC.run.begin()` instead
*/
SC.RunLoop.begin = SC.run.begin;

/**
  @deprecated
  @method

  Use `#js:SC.run.end()` instead
*/
SC.RunLoop.end = SC.run.end;

<|endoftext|>