<commit_before>var rndColor = function() {
   var bg_colour = Math.floor(Math.random() * 16777215).toString(16);
   bg_colour = "#"+("000000" + bg_colour).slice(-6);
   return bg_colour;
};
var sampleNames = [
   'Fe', 'Thomas', 'Kirstie', 'Wynell', 'Mario', 'Aretha', 'Cherryl', 'Ta',
   'Lindy', 'Karina', 'Sacha', 'Latesha', 'Miki', 'Janel', 'Leola', 'Romeo',
   'Roderick', 'Felica', 'Ilona', 'Nila', 'Patrina', 'Wes', 'Henry', 'Elvera',
   'Karrie', 'Jacklyn', 'Alethea', 'Emogene', 'Alphonso', 'Chandra', 'Beryl',
   'Lilly', 'Georgetta', 'Darrin', 'Deane', 'Rocio', 'Charissa', 'Simona',
   'Don', 'Arianne', 'Esther', 'Leonia', 'Karma', 'Rosemarie', 'Carolyn',
   'Miriam', 'Chastity', 'Vesta', 'Christian', 'Lashaun'
].sort();
var name = sampleNames[Math.floor(Math.random() * sampleNames.length)];
var color = rndColor();

function displayScreenMode(data) {
   var screenMode = $('#mode');
   screenMode.text(data.width + 'x' + data.height +
      (data.x >= 0 ? '+' + data.x : "" + data.x) +
      (data.y >= 0 ? '+' + data.y : "" + data.y) + ':' +
      data.scale
   );
}

function encodeScreen(data) {
   return data.width + ':' + data.height + ':' +
      data.x + ':' + data.y  + ':' +
      data.scale;
}

function decodeScreen(str) {
   var screenSplitted = str.split(':');

   return {
      width : +screenSplitted[0],
      height : +screenSplitted[1],
      x : +screenSplitted[2],
      y : +screenSplitted[3],
      scale : +screenSplitted[4]
   };
}

var screen = {
   width: window.innerWidth,
   height: window.innerHeight,
   x: 0,
   y: 0,
   scale: 1
};
var touchPoint = {
   x: 0,
   y: 0
};
var MAX_CANVAS_WIDTH = 250,
   scale;

var wams = new WAMS({screen: encodeScreen(screen), name: name, color: color});

$(document).ready(function() {
   var userID = $('#userID');
   userID.text(name);
   userID.css({ background: color });

   displayScreenMode(screen);
});

$(window).resize(function() {
   screen.width = window.innerWidth;
   screen.height = window.innerHeight;

   wams.description.screen = encodeScreen(screen);
   displayScreenMode(screen);
   wams.emit('resize_screen', {screen: encodeScreen(screen)});
   drawMinimap();
});

wams.on('adjust_workspace', function(data) {
   wams.description.screen = data.screen;
   data = decodeScreen(data.screen);
   displayScreenMode(data);
   screen = data;
});

function appendElement(data) {
   var elem = document.createElement(data.tag);
   for (var attr in data.attributes) {
      if (data.attributes.hasOwnProperty(attr)) {
         elem.setAttribute(attr, data.attributes[attr]);
      }
   }
   elem.innerHTML = data.innerHTML || "";

   var body = document.getElementsByTagName('body');
   body[0].appendChild(elem);

   wams.dispose();

   var elems = document.getElementsByClassName('ball');
   wams.addMT(elems);

   wams.on('touch', onTouch);
   wams.on('drag', onDrag);
   wams.on('release', onRelease);
}

function deleteElement(elem) {
   elem = $(elem);
   elem.remove();
}

function adjustOtherWorkspace(uuid, screen) {
   wams.getDescription(uuid).screen = screen;
}

function drawMinimap() {
   var canvas = document.getElementById('minimap'),
      ctx = canvas.getContext("2d");

   ctx.translate(0.5, 0.5);

   wams.emit('request_workspace_dimensions', '');
}

wams.on('workspace_dimensions', function(data) {
   var canvas = document.getElementById('minimap'),
      ctx = canvas.getContext('2d'),
      canvas_height, screen, color;

   scale = MAX_CANVAS_WIDTH / data.width;
   canvas_height = data.height * scale;

   ctx.clearRect(0, 0, canvas.width, canvas.height);
   canvas.width = MAX_CANVAS_WIDTH;
   canvas.height = canvas_height;

   wams.otherClients.forEach(function(client) {
      screen = decodeScreen(client.description.screen);
      color = client.description.color;
      ctx.beginPath();
         ctx.strokeStyle = color;
         ctx.setLineDash([7, 3]);
         ctx.rect(screen.x * scale + 1, screen.y * scale + 1,
           screen.width * scale - 2, screen.height * scale - 2);
      ctx.stroke();
   });

   screen = decodeScreen(wams.description.screen);
   color = wams.description.color;
   ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.setLineDash([7, 3]);
      ctx.rect(screen.x * scale + 1, screen.y * scale + 1,
        screen.width * scale - 2, screen.height * scale - 2);
   ctx.stroke();
});

var messageTypes = {
   new_element: function(data) {
      appendElement(data.element);
   },
   adjust_other_workspace: function(data) {
      adjustOtherWorkspace(data.metadata.uuid, data.metadata.screen);
      drawMinimap();
   }
};

wams.on(WAMS.when.message_received, function(data) {
   messageTypes[data.action] && messageTypes[data.action](data);
});

wams.on([WAMS.when.connection_ok,
   WAMS.when.user_connected,
   WAMS.when.user_disconnected,
   'adjust_workspace'].join(' '), function(ev) {
      drawMinimap();
});

function resize(elem, w, h) {
   elem = $(elem);
   elem.css({ width: w, height: h });
}
function liftZindex(elem, num) {
   elem = $(elem);
   elem.css({ zIndex: num || 10 });
}
function lowerZindex(elem, num) {
   elem = $(elem);
   elem.css({ zIndex: num || 1 });
}
function moveElement(elem, x, y) {
   elem = $(elem);
   if (elem.hasClass('ball')) {
      elem.css({
         left: x,
         top: y
      });
   }
}
function fixTouchPoint(elem, x, y) {
   elem = $(elem);
   touchPoint.x = x - elem.offset().left;
   touchPoint.y = y - elem.offset().top;
}
function clearTouchPoint(elem) {
   touchPoint.x = 0;
   touchPoint.y = 0;
}
function lock(elem, uuid) {
   elem = $(elem);
   elem.attr('data-lock', uuid || wams.uuid);
}
function unlock(elem) {
   elem = $(elem);
   elem.attr('data-lock', "");
}
function unlocked(elem, uuid) {
   elem = $(elem);
   return (elem.attr('data-lock') === "") ||
      (elem.attr('data-lock') === uuid);
}

function onTouch(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         lock(target);
         liftZindex(target);
         fixTouchPoint(target, touches[t].pageX, touches[t].pageY);
      }
   }
}

function onDrag(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         moveElement(target, touches[t].pageX - touchPoint.x,
            touches[t].pageY - touchPoint.y);
      }
   }
}

function onRelease(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         unlock(target);
         lowerZindex(target);
         clearTouchPoint(target);
      }
   }
}

function onRemoteTouch(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         lock(target, data.source);
         liftZindex(target, 5);
      }
   });
}

function onRemoteDrag(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         moveElement(target, element.x, element.y);
      }
   });
}

function onRemoteRelease(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         unlock(target);
         lowerZindex(target);
      }
   });
}

wams.on('enable_remote', function(data) {
   var elements = data.data.element,
      type = data.data.type,
      i, len;
   for (i = 0, len = elements.length; i < len; i++) {
      var element = elements[i];
      if (!document.getElementById(element.attributes.id)) {
         appendElement(element);
         moveElement('#' + element.attributes.id, element.x, element.y);
      }
      if (type === 'touch') {
         data.data.source = data.source;
         onRemoteTouch(data.data);
      } else if (type === 'drag') {
         data.data.source = data.source;
         onRemoteDrag(data.data);
      } else if (type === 'release') {
         data.data.source = data.source;
         onRemoteRelease(data.data);
      }
   }
});

wams.on('disable_remote', function(data) {
   var elements = data.data.element,
      i, len;
   for (i = 0, len = elements.length; i < len; i++) {
      var element = elements[i];
      deleteElement('#' + element.attributes.id);
   }
});
<commit_msg>feat(drawClients): move code to new function<commit_after>var rndColor = function() {
   var bg_colour = Math.floor(Math.random() * 16777215).toString(16);
   bg_colour = "#"+("000000" + bg_colour).slice(-6);
   return bg_colour;
};
var sampleNames = [
   'Fe', 'Thomas', 'Kirstie', 'Wynell', 'Mario', 'Aretha', 'Cherryl', 'Ta',
   'Lindy', 'Karina', 'Sacha', 'Latesha', 'Miki', 'Janel', 'Leola', 'Romeo',
   'Roderick', 'Felica', 'Ilona', 'Nila', 'Patrina', 'Wes', 'Henry', 'Elvera',
   'Karrie', 'Jacklyn', 'Alethea', 'Emogene', 'Alphonso', 'Chandra', 'Beryl',
   'Lilly', 'Georgetta', 'Darrin', 'Deane', 'Rocio', 'Charissa', 'Simona',
   'Don', 'Arianne', 'Esther', 'Leonia', 'Karma', 'Rosemarie', 'Carolyn',
   'Miriam', 'Chastity', 'Vesta', 'Christian', 'Lashaun'
].sort();
var name = sampleNames[Math.floor(Math.random() * sampleNames.length)];
var color = rndColor();

function displayScreenMode(data) {
   var screenMode = $('#mode');
   screenMode.text(data.width + 'x' + data.height +
      (data.x >= 0 ? '+' + data.x : "" + data.x) +
      (data.y >= 0 ? '+' + data.y : "" + data.y) + ':' +
      data.scale
   );
}

function encodeScreen(data) {
   return data.width + ':' + data.height + ':' +
      data.x + ':' + data.y  + ':' +
      data.scale;
}

function decodeScreen(str) {
   var screenSplitted = str.split(':');

   return {
      width : +screenSplitted[0],
      height : +screenSplitted[1],
      x : +screenSplitted[2],
      y : +screenSplitted[3],
      scale : +screenSplitted[4]
   };
}

var screen = {
   width: window.innerWidth,
   height: window.innerHeight,
   x: 0,
   y: 0,
   scale: 1
};
var touchPoint = {
   x: 0,
   y: 0
};
var MAX_CANVAS_WIDTH = 250,
   scale;

var wams = new WAMS({screen: encodeScreen(screen), name: name, color: color});

$(document).ready(function() {
   var userID = $('#userID');
   userID.text(name);
   userID.css({ background: color });

   displayScreenMode(screen);
});

$(window).resize(function() {
   screen.width = window.innerWidth;
   screen.height = window.innerHeight;

   wams.description.screen = encodeScreen(screen);
   displayScreenMode(screen);
   wams.emit('resize_screen', {screen: encodeScreen(screen)});
   drawMinimap();
});

wams.on('adjust_workspace', function(data) {
   wams.description.screen = data.screen;
   data = decodeScreen(data.screen);
   displayScreenMode(data);
   screen = data;
});

function appendElement(data) {
   var elem = document.createElement(data.tag);
   for (var attr in data.attributes) {
      if (data.attributes.hasOwnProperty(attr)) {
         elem.setAttribute(attr, data.attributes[attr]);
      }
   }
   elem.innerHTML = data.innerHTML || "";

   var body = document.getElementsByTagName('body');
   body[0].appendChild(elem);

   wams.dispose();

   var elems = document.getElementsByClassName('ball');
   wams.addMT(elems);

   wams.on('touch', onTouch);
   wams.on('drag', onDrag);
   wams.on('release', onRelease);
}

function deleteElement(elem) {
   elem = $(elem);
   elem.remove();
}

function adjustOtherWorkspace(uuid, screen) {
   wams.getDescription(uuid).screen = screen;
}

function drawMinimap() {
   var canvas = document.getElementById('minimap'),
      ctx = canvas.getContext("2d");

   ctx.translate(0.5, 0.5);

   wams.emit('request_workspace_dimensions', '');
}

wams.on('workspace_dimensions', function(data) {
   var canvas = document.getElementById('minimap'),
      ctx = canvas.getContext('2d'),
      canvas_height, screen, color;

   scale = MAX_CANVAS_WIDTH / data.width;
   canvas_height = data.height * scale;

   canvas.width = MAX_CANVAS_WIDTH;
   canvas.height = canvas_height;

   ctx.clearRect(0, 0, canvas.width, canvas.height);
   drawClients();
});

function drawClients() {
   var canvas = document.getElementById('minimap'),
      ctx = canvas.getContext('2d'),
      screen, color;

   wams.otherClients.forEach(function(client) {
      screen = decodeScreen(client.description.screen);
      color = client.description.color;
      ctx.beginPath();
         ctx.strokeStyle = color;
         ctx.setLineDash([7, 3]);
         ctx.rect(screen.x * scale + 1, screen.y * scale + 1,
           screen.width * scale - 2, screen.height * scale - 2);
      ctx.stroke();
   });

   screen = decodeScreen(wams.description.screen);
   color = wams.description.color;
   ctx.beginPath();
      ctx.strokeStyle = color;
      ctx.setLineDash([7, 3]);
      ctx.rect(screen.x * scale + 1, screen.y * scale + 1,
        screen.width * scale - 2, screen.height * scale - 2);
   ctx.stroke();
}

var messageTypes = {
   new_element: function(data) {
      appendElement(data.element);
   },
   adjust_other_workspace: function(data) {
      adjustOtherWorkspace(data.metadata.uuid, data.metadata.screen);
      drawMinimap();
   }
};

wams.on(WAMS.when.message_received, function(data) {
   messageTypes[data.action] && messageTypes[data.action](data);
});

wams.on([WAMS.when.connection_ok,
   WAMS.when.user_connected,
   WAMS.when.user_disconnected,
   'adjust_workspace'].join(' '), function(ev) {
      drawMinimap();
});

function resize(elem, w, h) {
   elem = $(elem);
   elem.css({ width: w, height: h });
}
function liftZindex(elem, num) {
   elem = $(elem);
   elem.css({ zIndex: num || 10 });
}
function lowerZindex(elem, num) {
   elem = $(elem);
   elem.css({ zIndex: num || 1 });
}
function moveElement(elem, x, y) {
   elem = $(elem);
   if (elem.hasClass('ball')) {
      elem.css({
         left: x,
         top: y
      });
   }
}
function fixTouchPoint(elem, x, y) {
   elem = $(elem);
   touchPoint.x = x - elem.offset().left;
   touchPoint.y = y - elem.offset().top;
}
function clearTouchPoint(elem) {
   touchPoint.x = 0;
   touchPoint.y = 0;
}
function lock(elem, uuid) {
   elem = $(elem);
   elem.attr('data-lock', uuid || wams.uuid);
}
function unlock(elem) {
   elem = $(elem);
   elem.attr('data-lock', "");
}
function unlocked(elem, uuid) {
   elem = $(elem);
   return (elem.attr('data-lock') === "") ||
      (elem.attr('data-lock') === uuid);
}

function onTouch(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         lock(target);
         liftZindex(target);
         fixTouchPoint(target, touches[t].pageX, touches[t].pageY);
      }
   }
}

function onDrag(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         moveElement(target, touches[t].pageX - touchPoint.x,
            touches[t].pageY - touchPoint.y);
      }
   }
}

function onRelease(ev) {
   var touches = ev.gesture.touches;
   for (var t = 0, len = touches.length; t < len; t++) {
      var target = ev.target;
      if (unlocked(target, wams.uuid)) {
         unlock(target);
         lowerZindex(target);
         clearTouchPoint(target);
      }
   }
}

function onRemoteTouch(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         lock(target, data.source);
         liftZindex(target, 5);
      }
   });
}

function onRemoteDrag(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         moveElement(target, element.x, element.y);
      }
   });
}

function onRemoteRelease(data) {
   data.element.forEach(function(element) {
      var target = document.getElementById(element.attributes.id);
      if (unlocked(target, data.source)) {
         unlock(target);
         lowerZindex(target);
      }
   });
}

wams.on('enable_remote', function(data) {
   var elements = data.data.element,
      type = data.data.type,
      i, len;
   for (i = 0, len = elements.length; i < len; i++) {
      var element = elements[i];
      if (!document.getElementById(element.attributes.id)) {
         appendElement(element);
         moveElement('#' + element.attributes.id, element.x, element.y);
      }
      if (type === 'touch') {
         data.data.source = data.source;
         onRemoteTouch(data.data);
      } else if (type === 'drag') {
         data.data.source = data.source;
         onRemoteDrag(data.data);
      } else if (type === 'release') {
         data.data.source = data.source;
         onRemoteRelease(data.data);
      }
   }
});

wams.on('disable_remote', function(data) {
   var elements = data.data.element,
      i, len;
   for (i = 0, len = elements.length; i < len; i++) {
      var element = elements[i];
      deleteElement('#' + element.attributes.id);
   }
});
<|endoftext|>


<commit_before>var argscheck = require('cordova/argscheck'),
	exec = require('cordova/exec');

var mediaObjects = null;
var Media = function (){

};
/**
 * This class provides access to the device media, interfaces to both sound and video
 *
 * @constructor
 * @param src                   The file name or url to play
 * @param successCallback       The callback to be called when the file is done playing.
 *                                  successCallback()
 * @param errorCallback         The callback to be called if there is an error.
 *                                  errorCallback(int errorCode) - OPTIONAL
 * @param statusCallback       The callback to be called when media status has changed.
 *                                  statusCallback(int statusCode) - OPTIONAL
 * @param msgCallback          The callback to be called when receive message from media(ex. position, subtitleChange etc)
 *                                  msgCallback(int messageType, any messageValue) - OPTIONAL
 */
Media.prototype.create = function(src, successCallback, errorCallback, statusCallback, msgCallback) {
    argscheck.checkArgs('sFFF', 'Media', arguments);
    mediaObjects = this;
    this.src = src;
    this.successCallback = successCallback;
    this.errorCallback = errorCallback;
    this.statusCallback = statusCallback;
    this.msgCallback = msgCallback;
    this._duration = -1;
    this._position = -1;
    exec(null, this.errorCallback, "toast.media", "create", this.src);
};

// Media messages
Media.MEDIA_STATE = 1;
Media.MEDIA_DURATION = 2;
Media.MEDIA_POSITION = 3;
Media.MEDIA_BUFFERINGPROGRESS = 4;
Media.MEDIA_SUBTITLE = 5;
Media.MEDIA_ERROR = 9;

// Media states
Media.MEDIA_NONE = 0;
Media.MEDIA_LOADEDMETADATA = 1;
Media.MEDIA_BUFFERINGSTART = 2;
Media.MEDIA_BUFFERINGCOMPLETE = 3;
Media.MEDIA_RUNNING = 4;
Media.MEDIA_PAUSED = 5;
Media.MEDIA_STOPPED = 6;
Media.MEDIA_MSG = ["None", "LoadedMetaData", "BufferingStart", "BufferingComplete", "Running", "Paused", "Stopped"];

// Media supported Adaptive Bitrate Streaming type
Media.ABS_TYPE_HLS = 0;
Media.ABS_TYPE_HAS = 1;
Media.ABS_TYPE_SS = 2;
Media.ABS_TYPE_WV = 3;
Media.ABS_TYPE_MSG = ["HLS","HAS","SmoothStreaming","Widevine"];

// Media supported Digital rights management type
Media.DRM_TYPE_PLAYREADY = 0;
Media.DRM_TYPE_MSG = ["PlayReady"];

// Media supported 3D Effect mode
Media.3D_TYPE_OFF = 0;
Media.3D_TYPE_TOPNBOTTOM = 1;
Media.3D_TYPE_SIDEBYSIDE = 2;
Media.3D_TYPE_2DTO3D = 3;
Media.3D_TYPE_MSG = ["OFF","TopBottom","SideBySide","2DTo3D"];

// Media error type
Media.ERR_ABORTED = 1;
Media.ERR_NETWORK = 2;
Media.ERR_DECODE = 3;
Media.ERR_SRC_NOT_SUPPORTED = 4;

Media.prototype.getSupportedABSType = function(){
	return Media.ABS_TYPE_MSG;
};

Media.prototype.getSupportedDRMType = function(){
	return Media.DRM_TYPE_MSG;
};

Media.prototype.getSupported3DType = function(){
	return Media.3D_TYPE_MSG;
}

Media.prototype.setDisplayRect = function(rect){
    exec(null, null, "toast.media", "setVideoDisplayRect", rect);
};

/**
 * Start or resume playing video file.
 *
 * @constructor
 * @param options     the options for playing the specific video(adaptive streaming, drm, 3D) contents. - OPTIONAL
 * @ ex)
 *    options : {
 *        runningPosition : int milliseconds, // video playback has to be started with runningPosition - OPTIONAL(default 0)
 *        abs : {
 *            type : int type, // Adaptive Bitrate Streaming type (refer Media supported Adaptive Bitrate Streaming type)
 *            data : object data // specitic Adaptive data(ex. BITRATES, STARTBITRATE, SKIPBITRATE) - OPTIONAL
 *        },
 *        drm : {
 *            type : int type, // Digital rights management type (refer Media supported Digital rights management type)
 *            data : object data // specitic DRM data(ex. CustomData, LicenseServer)
 *        },
 *        3D : int type // 3D Effect mode (refer Media supported 3D Effect mode) - OPTIONAL(default Media.3D_TYPE_OFF)
 *    }
 */

Media.prototype.play = function(options){
	exec(null, null, "toast.media", "startPlayingVideo", [this.src, options]);
};

Media.prototype.stop = function() {
	var me = this;
	exec(function() {
		me._position = 0;
	}, null, "toast.media", "stopPlayingVideo", null);
};

Media.prototype.seekTo = function(milliseconds) {
	var me = this;
	exec(function(p) {
		me._position = p;
	}, null, "toast.media", "seekToVideo", milliseconds);
};

Media.prototype.pause = function() {
	exec(null, null, "toast.media", "pausePlayingVideo", null);
};

Media.prototype.getDuration = function() {
	return this._duration;
};

Media.prototype.getCurrentPosition = function(success, fail) {
	var me = this;
	exec(function(p) {
		me._position = p;
		success(p);
	}, fail, "toast.media", "getCurrentPositionVideo", null);
};

/**
 * Media has message update.
 * PRIVATE
 *
 * @param msgType       The 'type' of update this is
 * @param value         Use of value is determined by the msgType
 */
Media.onStatus = function(msgType, value) {
    var media = mediaObjects;
    if(media) {
        switch(msgType) {
            case Media.MEDIA_STATE :
                media.statusCallback && media.statusCallback(value);
                if(value == Media.MEDIA_STOPPED) {
                    media.successCallback && media.successCallback();
                }
                break;
            case Media.MEDIA_DURATION :
                media._duration = value;
                break;
            case Media.MEDIA_ERROR :
                media.errorCallback && media.errorCallback(value);
                break;
            case Media.MEDIA_POSITION :
                media._position = Number(value);
                media.msgCallback && media.msgCallback(Media.MEDIA_POSITION, value);
                break;
            case Media.MEDIA_BUFFERINGPROGRESS :
                media.msgCallback && media.msgCallback(Media.MEDIA_BUFFERINGPROGRESS, value);
                break;
            case Media.MEDIA_SUBTITLE :
                media.msgCallback && media.msgCallback(Media.MEDIA_SUBTITLE, value);
                break;
            default :
                console.error && console.error("Unhandled Media.onStatus :: " + msgType);
                break;
        }
    }
    else {
         console.error && console.error("Received Media.onStatus callback for unknown media :: " + id);
    }
};

module.exports = new Media();<commit_msg>jshint check and bug fix<commit_after>'use strict';
var argscheck = require('cordova/argscheck'),
	exec = require('cordova/exec');

var mediaObjects = null;
var Media = function (){
    // Media messages
    this.MEDIA_STATE = 1;
    this.MEDIA_DURATION = 2;
    this.MEDIA_POSITION = 3;
    this.MEDIA_BUFFERINGPROGRESS = 4;
    this.MEDIA_SUBTITLE = 5;
    this.MEDIA_ERROR = 9;

    // Media states
    this.MEDIA_NONE = 0;
    this.MEDIA_LOADEDMETADATA = 1;
    this.MEDIA_BUFFERINGSTART = 2;
    this.MEDIA_BUFFERINGCOMPLETE = 3;
    this.MEDIA_RUNNING = 4;
    this.MEDIA_PAUSED = 5;
    this.MEDIA_STOPPED = 6;
    this.MEDIA_MSG = ['None', 'LoadedMetaData', 'BufferingStart', 'BufferingComplete', 'Running', 'Paused', 'Stopped'];

    // Media supported Adaptive Bitrate Streaming type
    this.ABS_TYPE_HLS = 0;
    this.ABS_TYPE_HAS = 1;
    this.ABS_TYPE_SS = 2;
    this.ABS_TYPE_WV = 3;
    this.ABS_TYPE_MSG = ['HLS','HAS','SmoothStreaming','Widevine'];

    // Media supported Digital rights management type
    this.DRM_TYPE_PLAYREADY = 0;
    this.DRM_TYPE_MSG = ['PlayReady'];

    // Media supported 3D Effect mode
    this.EFFECT_3D_TYPE_OFF = 0;
    this.EFFECT_3D_TYPE_TOPNBOTTOM = 1;
    this.EFFECT_3D_TYPE_SIDEBYSIDE = 2;
    this.EFFECT_3D_TYPE_2DTO3D = 3;
    this.EFFECT_3D_TYPE_MSG = ['OFF','TopBottom','SideBySide','2DTo3D'];

    // Media error type
    this.ERR_ABORTED = 1;
    this.ERR_NETWORK = 2;
    this.ERR_DECODE = 3;
    this.ERR_SRC_NOT_SUPPORTED = 4;
};
/**
 * This class provides access to the device media, interfaces to both sound and video
 *
 * @constructor
 * @param src                   The file name or url to play
 * @param successCallback       The callback to be called when the file is done playing.
 *                                  successCallback()
 * @param errorCallback         The callback to be called if there is an error.
 *                                  errorCallback(int errorCode) - OPTIONAL
 * @param statusCallback       The callback to be called when media status has changed.
 *                                  statusCallback(int statusCode) - OPTIONAL
 * @param msgCallback          The callback to be called when receive message from media(ex. position, subtitleChange etc)
 *                                  msgCallback(int messageType, any messageValue) - OPTIONAL
 */
Media.prototype.create = function(src, successCallback, errorCallback, statusCallback, msgCallback) {
    argscheck.checkArgs('sFFF', 'Media', arguments);
    mediaObjects = this;
    this.src = src;
    this.successCallback = successCallback;
    this.errorCallback = errorCallback;
    this.statusCallback = statusCallback;
    this.msgCallback = msgCallback;
    this._duration = -1;
    this._position = -1;
    exec(null, this.errorCallback, 'toast.media', 'create', this.src);
};

// Media messages
Media.MEDIA_STATE = 1;
Media.MEDIA_DURATION = 2;
Media.MEDIA_POSITION = 3;
Media.MEDIA_BUFFERINGPROGRESS = 4;
Media.MEDIA_SUBTITLE = 5;
Media.MEDIA_ERROR = 9;

// Media states
Media.MEDIA_NONE = 0;
Media.MEDIA_LOADEDMETADATA = 1;
Media.MEDIA_BUFFERINGSTART = 2;
Media.MEDIA_BUFFERINGCOMPLETE = 3;
Media.MEDIA_RUNNING = 4;
Media.MEDIA_PAUSED = 5;
Media.MEDIA_STOPPED = 6;
Media.MEDIA_MSG = ['None', 'LoadedMetaData', 'BufferingStart', 'BufferingComplete', 'Running', 'Paused', 'Stopped'];

// Media supported Adaptive Bitrate Streaming type
Media.ABS_TYPE_HLS = 0;
Media.ABS_TYPE_HAS = 1;
Media.ABS_TYPE_SS = 2;
Media.ABS_TYPE_WV = 3;
Media.ABS_TYPE_MSG = ['HLS','HAS','SmoothStreaming','Widevine'];

// Media supported Digital rights management type
Media.DRM_TYPE_PLAYREADY = 0;
Media.DRM_TYPE_MSG = ['PlayReady'];

// Media supported 3D Effect mode
Media.EFFECT_3D_TYPE_OFF = 0;
Media.EFFECT_3D_TYPE_TOPNBOTTOM = 1;
Media.EFFECT_3D_TYPE_SIDEBYSIDE = 2;
Media.EFFECT_3D_TYPE_2DTO3D = 3;
Media.EFFECT_3D_TYPE_MSG = ['OFF','TopBottom','SideBySide','2DTo3D'];

// Media error type
Media.ERR_ABORTED = 1;
Media.ERR_NETWORK = 2;
Media.ERR_DECODE = 3;
Media.ERR_SRC_NOT_SUPPORTED = 4;

Media.prototype.getSupportedABSType = function(){
	return Media.ABS_TYPE_MSG;
};

Media.prototype.getSupportedDRMType = function(){
	return Media.DRM_TYPE_MSG;
};

Media.prototype.getSupported3DType = function(){
	return Media.EFFECT_3D_TYPE_MSG;
};

Media.prototype.setDisplayRect = function(rect){
    exec(null, null, 'toast.media', 'setVideoDisplayRect', rect);
};

/**
 * Start or resume playing video file.
 *
 * @constructor
 * @param options     the options for playing the specific video(adaptive streaming, drm, 3D) contents. - OPTIONAL
 * @ ex)
 *    options : {
 *        runningPosition : int milliseconds, // video playback has to be started with runningPosition - OPTIONAL(default 0)
 *        abs : {
 *            type : int type, // Adaptive Bitrate Streaming type (refer Media supported Adaptive Bitrate Streaming type)
 *            data : object data // specitic Adaptive data(ex. BITRATES, STARTBITRATE, SKIPBITRATE) - OPTIONAL
 *        },
 *        drm : {
 *            type : int type, // Digital rights management type (refer Media supported Digital rights management type)
 *            data : object data // specitic DRM data(ex. CustomData, LicenseServer)
 *        },
 *        3D : int type // 3D Effect mode (refer Media supported 3D Effect mode) - OPTIONAL(default Media.3D_TYPE_OFF)
 *    }
 */

Media.prototype.play = function(options){
	exec(null, null, 'toast.media', 'startPlayingVideo', [this.src, options]);
};

Media.prototype.stop = function() {
	var me = this;
	exec(function() {
		me._position = 0;
	}, null, 'toast.media', 'stopPlayingVideo', null);
};

Media.prototype.seekTo = function(milliseconds) {
	var me = this;
	exec(function(p) {
		me._position = p;
	}, null, 'toast.media', 'seekToVideo', milliseconds);
};

Media.prototype.pause = function() {
	exec(null, null, 'toast.media', 'pausePlayingVideo', null);
};

Media.prototype.getDuration = function() {
	return this._duration;
};

Media.prototype.getCurrentPosition = function(success, fail) {
	var me = this;
	exec(function(p) {
		me._position = p;
		success(p);
	}, fail, 'toast.media', 'getCurrentPositionVideo', null);
};

/**
 * Media has message update.
 * PRIVATE
 *
 * @param msgType       The 'type' of update this is
 * @param value         Use of value is determined by the msgType
 */
Media.onStatus = function(msgType, value) {
    var media = mediaObjects;
    if(media) {
        switch(msgType) {
            case Media.MEDIA_STATE :
                media.statusCallback && media.statusCallback(value);
                if(value == Media.MEDIA_STOPPED) {
                    media.successCallback && media.successCallback();
                }
                break;
            case Media.MEDIA_DURATION :
                media._duration = value;
                break;
            case Media.MEDIA_ERROR :
                media.errorCallback && media.errorCallback(value);
                break;
            case Media.MEDIA_POSITION :
                media._position = Number(value);
                media.msgCallback && media.msgCallback(Media.MEDIA_POSITION, value);
                break;
            case Media.MEDIA_BUFFERINGPROGRESS :
                media.msgCallback && media.msgCallback(Media.MEDIA_BUFFERINGPROGRESS, value);
                break;
            case Media.MEDIA_SUBTITLE :
                media.msgCallback && media.msgCallback(Media.MEDIA_SUBTITLE, value);
                break;
            default :
                console.error && console.error('Unhandled Media.onStatus :: ' + msgType);
                break;
        }
    }
    else {
         console.error && console.error('Received Media.onStatus callback for unknown media');
    }
};

module.exports = new Media();<|endoftext|>


<commit_before>// Read configuration from dev_config.json (or production_config.json)
var config = require('getconfig');
var _ = require('underscore');
var pretty_data  = require('pretty-data');

var graphHost = config.graphServer.graphHost;
var graphPort = config.graphServer.graphPort;
var isRexster = config.graphServer.isRexster; //leaving both for testing, but planning to remove rexster support.

var graphUri;
if (isRexster) {
  var graphName = config.graphServer.graphName;
  var rex = 'http://' + graphHost + ':' + graphPort;
  graphUri = rex + '/graphs/' + graphName;
}
else {
  var graphRootPath = config.graphServer.graphRootPath;
  graphUri = 'http://' + graphHost + ':' + graphPort + '/' + graphRootPath;
}

// maybe use [request](https://github.com/request/request) for pulling
// data from rexster.
var xhr = require('request');

// Query a node based on an ID.
// Usage: curl -XGET :3000/api/nodes/<id>/inEdges
// Returns: JSON array of triples of objects associated with the requested ID, or an error object
exports.getEdges = function (req, res) {
  var id = encodeURIComponent(req.params.id);
  var err;
  var pageSize = 10;
  if (req.query.pageSize) {
    pageSize = Number(req.query.pageSize);
  }
  var page = 0;
  if (req.query.page) {
    page = Number(req.query.page);
  }
  var start = Number(pageSize * page);
  var end = Number(start + pageSize);

  var queryURL;
  var gremlinQ;
  var rexsterPaging;
  var gremlinFiltering;
  var queryString;
  if (req.query.inEdges) {
    if (isRexster) {
      gremlinQ = 'g.v(\"' + id + '\")';
      rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
      gremlinFiltering = '[' + start + '..' + end + ']';

      gremlinQ = gremlinQ + '.inE.outV.path';
      if (start > 0) {
        gremlinQ = 'g.v(\"' + id + '\").inE' + gremlinFiltering + '.outV.path';
      }
      else {
        gremlinQ = gremlinQ + rexsterPaging;
      }
      queryURL = graphUri + "/tp/gremlin?script=" + gremlinQ;
    }
    else {
      queryString = JSON.stringify({"page": page, "pageSize": pageSize});
      queryURL = graphUri + "/inEdges/" + id + '?q=' + queryString;
    }
    console.log("getEdges() query = " + queryURL);

    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          err = "Error executing search for incoming edges: " + error;
          console.error(error);
          return res.status(500).send({error: err, gremlinQuery: gremlinQ});
        }
        var status = response.statusCode;
        var results = (JSON.parse(body)).results;

        //console.info(">>> getInEdges() response:\n\t" + results.length);

        res.status(status).send(body);
      }
    );
  }
  else if (req.query.outEdges) {
    if (isRexster) {
      gremlinQ = 'g.v(\"' + id + '\")';
      rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
      gremlinFiltering = '[' + start + '..' + end + ']';

      gremlinQ = gremlinQ + '.outE.inV.path';
      if (start > 0) {
        gremlinQ = 'g.v(\"' + id + '\").outE' + gremlinFiltering + '.inV.path';
      }
      else {
        gremlinQ = gremlinQ + rexsterPaging;
      }

      queryURL = graphUri + "/tp/gremlin?script=" + gremlinQ;
    }
    else {
      queryString = JSON.stringify({"page": page, "pageSize": pageSize});
      queryURL = graphUri + "/outEdges/" + id + '?q=' + queryString;
    }
    console.log("getEdges() query = " + queryURL);

    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          err = "Error executing search for outgoing edges: " + error;
          console.error(error);
          return res.status(500).send({error: err, gremlinQuery: gremlinQ});
        }
        var status = response.statusCode;
        var results = (JSON.parse(body)).results;

        //console.info(">>> getOutEdges() response:\n\t" + results.length);

        res.status(status).send(body);
      }
    );
  }
  else {
    console.error("Unknown edge type in request '" + JSON.stringify(req.query) + "'!");
  }
};

// Query a node based on an ID.
// Usage: curl -XGET :3000/api/nodes/<id>
// Returns: JSON object of the requested ID, or an error object
exports.getNode = function (req, res) {
  var id = encodeURIComponent(req.params.id);
  var err;

  var status = 404;
  var results = {};

  var queryURL;
  if (isRexster) {
    queryURL = graphUri + '/vertices/' + id;
  }
  else {
    queryURL = graphUri + "/vertex/" + id;
  }
  console.log("getNode() query = " + queryURL);

  xhr(queryURL,
    function (error, response, body) {
      if (error) {
        err = "Error obtaining node: " + error;
        console.error(error);
        return res.status(500).send({error: err, node: id});
      }
      status = response.statusCode;
      //TODO: status code other than 200 - redirect page to results
      results = (JSON.parse(body)).results;
      //TODO: empty result - display pop up and return to results

      //TODO: remove after testing
      //var xml = '<stixCommon:Exploit_Target xmlns:stixCommon=\"http://stix.mitre.org/common-1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"stucco:vulnerability-95a58902-594d-4c46-8bb8-dca5834f6682\" xsi:type=\"et:ExploitTargetType\"><et:Title xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\">Vulnerability<\/et:Title><et:Vulnerability xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\"><et:Description>WebGate eDVR Manager ActiveX Controls CVE-2015-2098 Multiple Buffer Overflow Vulnerabilities WebGate eDVR Manager is prone to multiple buffer-overflow vulnerabilities because it fails to perform boundary checks before copying user-supplied data to insufficiently sized memory buffer. The controls are identified.<\/et:Description><et:Short_Description>WebGate eDVR Manager ActiveX Controls CVE-2015-2098 Multiple Buffer Overflow Vulnerabilities<\/et:Short_Description><et:CVE_ID>CVE-nnnn-nnnn<\/et:CVE_ID><et:OSVDB_ID>72838453<\/et:OSVDB_ID><et:Source>NVD<\/et:Source><et:Published_DateTime>2015-03-28T00:30:00.000-04:00<\/et:Published_DateTime><et:References><stixCommon:Reference>http://support.microsoft.com/kb/240797<\/stixCommon:Reference><stixCommon:Reference>Second<\/stixCommon:Reference><stixCommon:Reference>Third<\/stixCommon:Reference><\/et:References><\/et:Vulnerability><et:Potential_COAs xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\"><et:Potential_COA><stixCommon:Course_Of_Action idref=\"stucco:vulnerability-9d31d334-93f5-4819-ac1e-8ea8ce957cdf\" xsi:type=\"coa:CourseOfActionType\"/><\/et:Potential_COA><\/et:Potential_COAs><\/stixCommon:Exploit_Target>';
      //results["sourceDocument"] = pretty_data.pd.xml(xml);

      if (results.sourceDocument) {
        results.sourceDocument = pretty_data.pd.xml(results.sourceDocument);
      }

      //console.info(">>> getNode() response:\n\t" + JSON.stringify(results));

      res.status(status).send(results);
    }
  );
};

// Search knowledge graph.
// Usage: curl -XGET :3000/api/search
// Required parameters:
//  * q: search query (string)
// Returns: JSON array of objects matching the query, or an error object
exports.search = function (req, res) {
  var status = 200;
  var q = req.query;
  var err;

  var pageSize = 20;
  if (req.query.pageSize) {
    pageSize = Number(req.query.pageSize);
  }
  var page = 0;
  if (req.query.page) {
    page = Number(req.query.page);
  }
  var start = Number(pageSize * page);
  var end = Number(start + pageSize);

  // Get the first key - other key/values are ignored
  var keys = Object.keys(q);
  if (! keys) {
    err = "Malformed search query: no query defined.";
    console.warn(err);
    return res.status(500).send({error: err});
  }
  var key = keys[0];
  var val = q[key];
  if (!val) {
    err = "Malformed search query: no value defined. Query: " + JSON.stringify(q);
    console.warn(err);
    return res.status(500).send({error: err});
  }

  var queryURL;
  if (isRexster) {
    // Set the gremlin query.
    var gremlinQ = '?script=g.V(\"' + key + '\",\"' + val + '\")';
    if (_.contains(config.indices.fulltext, key)) {
      gremlinQ = '?script=g.query().has(\"' + key + '\",CONTAINS,\"' + val + '\").vertices()';
    }
    var rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
    queryURL = graphUri + '/tp/gremlin' + gremlinQ + rexsterPaging;
  }
  else {
    var queryString = JSON.stringify(q);
    queryURL = graphUri + "/search?q=" + queryString;
  }
  console.log("search() query = " + queryURL);

  xhr(queryURL,
    function (error, response, body) {
      if (error) {
        err = "Error executing search query: " + error;
        console.error(error);
        return res.status(500).send({error: err, gremlinQuery: gremlinQ});
      }
      status = response.statusCode;
      var results = (JSON.parse(body)).results;
      //console.info(">>> search() response:\n\t" + JSON.stringify(results));
      if ((JSON.parse(body)).count === 0) { status = 404; }
      return res.status(status).send(body);
    }
  );
};

// Get the count of nodes or edges in the graph
// Usage: curl -XGET :3000/api/count
// Required parameters:
//  * q: search query (string)
// Optional parameters:
//  * t: type: vertex (default) or edge
// Returns: JSON object of {"count": <count>}
exports.countNodes = function (req, res) {
  if (isRexster) {
    count(req, res, 'node');
  }
  else {
    //TODO: support query & count
    var queryURL = graphUri + "/count/vertices";
    console.log("countNodes() query = " + queryURL);
    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          var err = "Error getting node count: " + error;
          console.error(error);
          return res.status(500).send({error: err});
        }
        var statusCode = response.statusCode;
        //console.info(">>> countNodes() response:\n\t" + JSON.stringify(body));
        var result = {count: (JSON.parse(body)).count};
        return res.status(statusCode).send(result);
      }
    );
  }
};

exports.countEdges = function (req, res) {
  if (isRexster) {
    count(req, res, 'edge');
  }
  else {
    //TODO: support query & count
    var queryURL = graphUri + "/count/edges";
    console.log("countEdges() query = " + queryURL);
    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          var err = "Error getting edge count: " + error;
          console.error(error);
          return res.status(500).send({error: err});
        }
        var statusCode = response.statusCode;
        //console.info(">>> countEdges() response:\n\t" + JSON.stringify(body));
        var result = {count: (JSON.parse(body)).count};
        return res.status(statusCode).send(result);
      }
    );
  }
};

// Count nodes or edges.
//NOTE: only invoked by rexster
function count(req, res, type) {
  var status = 200;
  var q = req.query;
  var gremlinQ;
  var err;

  // Either query based on a key/value or get all nodes/edges.
  var keys = Object.keys(q);
  if (keys.length > 0) {
    var key = keys[0];
    var val = q[key];
    if (!val) {
      err = "Malformed search query: no value defined. Query: " + JSON.stringify(q);
      console.warn(err);
      return res.status(500).send({error: err});
    }
    gremlinQ = '?script=g.V("' + key + '","' + val + '").count()';
    if (type === 'edge' || type === 'edges') {
      gremlinQ = '?script=g.E("' + key + '","' + val + '").count()';
    }
  }
  else {
    gremlinQ = '?script=g.V().count()';
    if (type === 'edge' || type === 'edges') {
      gremlinQ = '?script=g.E().count()';
    }
  }

  // Query rexster using gremlin to get the count.
  console.log("count() query = " + graphUri + '/tp/gremlin' + gremlinQ);
  xhr(graphUri + '/tp/gremlin' + gremlinQ,
    function (error, response, body) {
      if (error) {
        err = "Error getting " + type + " count: " + error;
        console.error(error);
        return res.status(500).send({error: err});
      }
      status = response.statusCode;
      var results = (JSON.parse(body)).results;
      console.info(">>> count() response:\n\t" + JSON.stringify(results));
      var result = {count: (JSON.parse(body)).results[0]};
      if (result.count === 0) { status = 404; }
      return res.status(status).send(result);
    }
  );
}

//TODO: Implement this if needed
exports.updateNode = function (req, res) {
  var status = 200; // all good
  var body = req.body;

  res.status(status).send(body);
};

<commit_msg>vertex count now takes an optional search query<commit_after>// Read configuration from dev_config.json (or production_config.json)
var config = require('getconfig');
var _ = require('underscore');
var pretty_data  = require('pretty-data');

var graphHost = config.graphServer.graphHost;
var graphPort = config.graphServer.graphPort;
var isRexster = config.graphServer.isRexster; //leaving both for testing, but planning to remove rexster support.

var graphUri;
if (isRexster) {
  var graphName = config.graphServer.graphName;
  var rex = 'http://' + graphHost + ':' + graphPort;
  graphUri = rex + '/graphs/' + graphName;
}
else {
  var graphRootPath = config.graphServer.graphRootPath;
  graphUri = 'http://' + graphHost + ':' + graphPort + '/' + graphRootPath;
}

// maybe use [request](https://github.com/request/request) for pulling
// data from rexster.
var xhr = require('request');

// Query a node based on an ID.
// Usage: curl -XGET :3000/api/nodes/<id>/inEdges
// Returns: JSON array of triples of objects associated with the requested ID, or an error object
exports.getEdges = function (req, res) {
  var id = encodeURIComponent(req.params.id);
  var err;
  var pageSize = 10;
  if (req.query.pageSize) {
    pageSize = Number(req.query.pageSize);
  }
  var page = 0;
  if (req.query.page) {
    page = Number(req.query.page);
  }
  var start = Number(pageSize * page);
  var end = Number(start + pageSize);

  var queryURL;
  var gremlinQ;
  var rexsterPaging;
  var gremlinFiltering;
  var queryString;
  if (req.query.inEdges) {
    if (isRexster) {
      gremlinQ = 'g.v(\"' + id + '\")';
      rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
      gremlinFiltering = '[' + start + '..' + end + ']';

      gremlinQ = gremlinQ + '.inE.outV.path';
      if (start > 0) {
        gremlinQ = 'g.v(\"' + id + '\").inE' + gremlinFiltering + '.outV.path';
      }
      else {
        gremlinQ = gremlinQ + rexsterPaging;
      }
      queryURL = graphUri + "/tp/gremlin?script=" + gremlinQ;
    }
    else {
      queryString = JSON.stringify({"page": page, "pageSize": pageSize});
      queryURL = graphUri + "/inEdges/" + id + '?q=' + queryString;
    }
    console.log("getEdges() query = " + queryURL);

    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          err = "Error executing search for incoming edges: " + error;
          console.error(error);
          return res.status(500).send({error: err, gremlinQuery: gremlinQ});
        }
        var status = response.statusCode;
        var results = (JSON.parse(body)).results;

        //console.info(">>> getInEdges() response:\n\t" + results.length);

        res.status(status).send(body);
      }
    );
  }
  else if (req.query.outEdges) {
    if (isRexster) {
      gremlinQ = 'g.v(\"' + id + '\")';
      rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
      gremlinFiltering = '[' + start + '..' + end + ']';

      gremlinQ = gremlinQ + '.outE.inV.path';
      if (start > 0) {
        gremlinQ = 'g.v(\"' + id + '\").outE' + gremlinFiltering + '.inV.path';
      }
      else {
        gremlinQ = gremlinQ + rexsterPaging;
      }

      queryURL = graphUri + "/tp/gremlin?script=" + gremlinQ;
    }
    else {
      queryString = JSON.stringify({"page": page, "pageSize": pageSize});
      queryURL = graphUri + "/outEdges/" + id + '?q=' + queryString;
    }
    console.log("getEdges() query = " + queryURL);

    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          err = "Error executing search for outgoing edges: " + error;
          console.error(error);
          return res.status(500).send({error: err, gremlinQuery: gremlinQ});
        }
        var status = response.statusCode;
        var results = (JSON.parse(body)).results;

        //console.info(">>> getOutEdges() response:\n\t" + results.length);

        res.status(status).send(body);
      }
    );
  }
  else {
    console.error("Unknown edge type in request '" + JSON.stringify(req.query) + "'!");
  }
};

// Query a node based on an ID.
// Usage: curl -XGET :3000/api/nodes/<id>
// Returns: JSON object of the requested ID, or an error object
exports.getNode = function (req, res) {
  var id = encodeURIComponent(req.params.id);
  var err;

  var status = 404;
  var results = {};

  var queryURL;
  if (isRexster) {
    queryURL = graphUri + '/vertices/' + id;
  }
  else {
    queryURL = graphUri + "/vertex/" + id;
  }
  console.log("getNode() query = " + queryURL);

  xhr(queryURL,
    function (error, response, body) {
      if (error) {
        err = "Error obtaining node: " + error;
        console.error(error);
        return res.status(500).send({error: err, node: id});
      }
      status = response.statusCode;
      //TODO: status code other than 200 - redirect page to results
      results = (JSON.parse(body)).results;
      //TODO: empty result - display pop up and return to results

      //TODO: remove after testing
      //var xml = '<stixCommon:Exploit_Target xmlns:stixCommon=\"http://stix.mitre.org/common-1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" id=\"stucco:vulnerability-95a58902-594d-4c46-8bb8-dca5834f6682\" xsi:type=\"et:ExploitTargetType\"><et:Title xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\">Vulnerability<\/et:Title><et:Vulnerability xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\"><et:Description>WebGate eDVR Manager ActiveX Controls CVE-2015-2098 Multiple Buffer Overflow Vulnerabilities WebGate eDVR Manager is prone to multiple buffer-overflow vulnerabilities because it fails to perform boundary checks before copying user-supplied data to insufficiently sized memory buffer. The controls are identified.<\/et:Description><et:Short_Description>WebGate eDVR Manager ActiveX Controls CVE-2015-2098 Multiple Buffer Overflow Vulnerabilities<\/et:Short_Description><et:CVE_ID>CVE-nnnn-nnnn<\/et:CVE_ID><et:OSVDB_ID>72838453<\/et:OSVDB_ID><et:Source>NVD<\/et:Source><et:Published_DateTime>2015-03-28T00:30:00.000-04:00<\/et:Published_DateTime><et:References><stixCommon:Reference>http://support.microsoft.com/kb/240797<\/stixCommon:Reference><stixCommon:Reference>Second<\/stixCommon:Reference><stixCommon:Reference>Third<\/stixCommon:Reference><\/et:References><\/et:Vulnerability><et:Potential_COAs xmlns:et=\"http://stix.mitre.org/ExploitTarget-1\"><et:Potential_COA><stixCommon:Course_Of_Action idref=\"stucco:vulnerability-9d31d334-93f5-4819-ac1e-8ea8ce957cdf\" xsi:type=\"coa:CourseOfActionType\"/><\/et:Potential_COA><\/et:Potential_COAs><\/stixCommon:Exploit_Target>';
      //results["sourceDocument"] = pretty_data.pd.xml(xml);

      if (results.sourceDocument) {
        results.sourceDocument = pretty_data.pd.xml(results.sourceDocument);
      }

      //console.info(">>> getNode() response:\n\t" + JSON.stringify(results));

      res.status(status).send(results);
    }
  );
};

// Search knowledge graph.
// Usage: curl -XGET :3000/api/search
// Required parameters:
//  * q: search query (string)
// Returns: JSON array of objects matching the query, or an error object
exports.search = function (req, res) {
  var status = 200;
  var q = req.query;
  var err;

  var pageSize = 20;
  if (req.query.pageSize) {
    pageSize = Number(req.query.pageSize);
  }
  var page = 0;
  if (req.query.page) {
    page = Number(req.query.page);
  }
  var start = Number(pageSize * page);
  var end = Number(start + pageSize);

  // Get the first key - other key/values are ignored
  var keys = Object.keys(q);
  if (! keys) {
    err = "Malformed search query: no query defined.";
    console.warn(err);
    return res.status(500).send({error: err});
  }
  var key = keys[0];
  var val = q[key];
  if (!val) {
    err = "Malformed search query: no value defined. Query: " + JSON.stringify(q);
    console.warn(err);
    return res.status(500).send({error: err});
  }

  var queryURL;
  if (isRexster) {
    // Set the gremlin query.
    var gremlinQ = '?script=g.V(\"' + key + '\",\"' + val + '\")';
    if (_.contains(config.indices.fulltext, key)) {
      gremlinQ = '?script=g.query().has(\"' + key + '\",CONTAINS,\"' + val + '\").vertices()';
    }
    var rexsterPaging = '&rexster.offset.start=' + start + '&rexster.offset.end=' + end + '&returnTotal=true';
    queryURL = graphUri + '/tp/gremlin' + gremlinQ + rexsterPaging;
  }
  else {
    var queryString = JSON.stringify(q);
    queryURL = graphUri + "/search?q=" + queryString;
  }
  console.log("search() query = " + queryURL);

  xhr(queryURL,
    function (error, response, body) {
      if (error) {
        err = "Error executing search query: " + error;
        console.error(error);
        return res.status(500).send({error: err, gremlinQuery: gremlinQ});
      }
      status = response.statusCode;
      var results = (JSON.parse(body)).results;
      //console.info(">>> search() response:\n\t" + JSON.stringify(results));
      if ((JSON.parse(body)).count === 0) { status = 404; }
      return res.status(status).send(body);
    }
  );
};

// Get the count of nodes or edges in the graph
// Usage: curl -XGET :3000/api/count
// Required parameters:
//  * q: search query (string)
// Optional parameters:
//  * t: type: vertex (default) or edge
// Returns: JSON object of {"count": <count>}
exports.countNodes = function (req, res) {
  if (isRexster) {
    count(req, res, 'node');
  }
  else {
    var q = req.query;
    var keys = Object.keys(q);
    var queryURL;
    if (keys) {
      var queryString = JSON.stringify(q);
      queryURL = graphUri + "/count/vertices?q=" + queryString;
    }
    else {
      queryURL = graphUri + "/count/vertices";
    }

    console.log("countNodes() query = " + queryURL);
    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          var err = "Error getting node count: " + error;
          console.error(error);
          return res.status(500).send({error: err});
        }
        var statusCode = response.statusCode;
        //console.info(">>> countNodes() response:\n\t" + JSON.stringify(body));
        var result = {count: (JSON.parse(body)).count};
        return res.status(statusCode).send(result);
      }
    );
  }
};

exports.countEdges = function (req, res) {
  if (isRexster) {
    count(req, res, 'edge');
  }
  else {
    //TODO: support query & count, like countNodes, if/when needed.
    var queryURL = graphUri + "/count/edges";
    console.log("countEdges() query = " + queryURL);
    xhr(queryURL,
      function (error, response, body) {
        if (error) {
          var err = "Error getting edge count: " + error;
          console.error(error);
          return res.status(500).send({error: err});
        }
        var statusCode = response.statusCode;
        //console.info(">>> countEdges() response:\n\t" + JSON.stringify(body));
        var result = {count: (JSON.parse(body)).count};
        return res.status(statusCode).send(result);
      }
    );
  }
};

// Count nodes or edges.
//NOTE: only invoked by rexster
function count(req, res, type) {
  var status = 200;
  var q = req.query;
  var gremlinQ;
  var err;

  // Either query based on a key/value or get all nodes/edges.
  var keys = Object.keys(q);
  if (keys.length > 0) {
    var key = keys[0];
    var val = q[key];
    if (!val) {
      err = "Malformed search query: no value defined. Query: " + JSON.stringify(q);
      console.warn(err);
      return res.status(500).send({error: err});
    }
    gremlinQ = '?script=g.V("' + key + '","' + val + '").count()';
    if (type === 'edge' || type === 'edges') {
      gremlinQ = '?script=g.E("' + key + '","' + val + '").count()';
    }
  }
  else {
    gremlinQ = '?script=g.V().count()';
    if (type === 'edge' || type === 'edges') {
      gremlinQ = '?script=g.E().count()';
    }
  }

  // Query rexster using gremlin to get the count.
  console.log("count() query = " + graphUri + '/tp/gremlin' + gremlinQ);
  xhr(graphUri + '/tp/gremlin' + gremlinQ,
    function (error, response, body) {
      if (error) {
        err = "Error getting " + type + " count: " + error;
        console.error(error);
        return res.status(500).send({error: err});
      }
      status = response.statusCode;
      var results = (JSON.parse(body)).results;
      console.info(">>> count() response:\n\t" + JSON.stringify(results));
      var result = {count: (JSON.parse(body)).results[0]};
      if (result.count === 0) { status = 404; }
      return res.status(status).send(result);
    }
  );
}

//TODO: Implement this if needed
exports.updateNode = function (req, res) {
  var status = 200; // all good
  var body = req.body;

  res.status(status).send(body);
};

<|endoftext|>


<commit_before>var Gauge = {
  value: 0,
  max: 11000,
  create: function (camera, UI) {

    this.UI = UI;

    this.camera = camera;

    var texture = new THREE.TextureLoader().load('assets/img/graduation.png');
    this.marker = new THREE.Mesh(new THREE.BoxGeometry(0.78, 2, 0), new THREE.MeshBasicMaterial( { map: texture, transparent: true, color: 0xffffff }));
    this.marker.position.set(-0.6,0,-1.8);

    this.location = new THREE.Mesh(new THREE.SphereGeometry(0.05, 7, 7), new THREE.MeshBasicMaterial( { color: 0xff0000 }));
    this.location.position.set(0,0,0);
    this.marker.add(this.location);

    camera.add(this.marker);

    this.createText();

    return this;
  },

  createText: function() {

    if(!this.UI.font){
      this.UI.loadFont(function() {
        this.createText(this.UI);
      }.bind(this));
      return;
    }

    this.locationText = new THREE.Mesh(new THREE.TextGeometry("", {font: this.UI.font, size: 0.05, height: 0.01}), new THREE.MeshBasicMaterial( { color: 0xff0000 }));
    this.locationText.position.set(0.1, -0.02, 0);
    //this.locationText.rotateOnAxis(new THREE.Vector3(0, 1, 1), Math.PI/4);
    this.location.add(this.locationText);
  },

  update: function () {
    this.value = Math.round(this.camera.position.y / 50) - this.max;
    this.location.position.setY(this.value/this.max * 2 + 1.25);
    if(this.locationText){
      this.locationText.geometry = new THREE.TextGeometry(this.value + "m", {font: this.UI.font, size: 0.05, height: 0.01});
      //this.locationText.computeBoundingBox();
    }
  }

};

module.exports = Gauge;<commit_msg>Set depth level to ~ -8500m<commit_after>var Gauge = {
  value: 0,
  max: 11000,
  create: function (camera, UI) {

    this.UI = UI;

    this.camera = camera;

    var texture = new THREE.TextureLoader().load('assets/img/graduation.png');
    this.marker = new THREE.Mesh(new THREE.BoxGeometry(0.78, 2, 0), new THREE.MeshBasicMaterial( { map: texture, transparent: true, color: 0xffffff }));
    this.marker.position.set(-0.6,0,-1.8);

    this.location = new THREE.Mesh(new THREE.SphereGeometry(0.05, 7, 7), new THREE.MeshBasicMaterial( { color: 0xff0000 }));
    this.location.position.set(0,0,0);
    this.marker.add(this.location);

    camera.add(this.marker);

    this.createText();

    return this;
  },

  createText: function() {

    if(!this.UI.font){
      this.UI.loadFont(function() {
        this.createText(this.UI);
      }.bind(this));
      return;
    }

    this.locationText = new THREE.Mesh(new THREE.TextGeometry("", {font: this.UI.font, size: 0.05, height: 0.01}), new THREE.MeshBasicMaterial( { color: 0xff0000 }));
    this.locationText.position.set(0.1, -0.02, 0);
    //this.locationText.rotateOnAxis(new THREE.Vector3(0, 1, 1), Math.PI/4);
    this.location.add(this.locationText);
  },

  update: function () {
    this.value = Math.round(this.camera.position.y / 50) - this.max;
    this.location.position.setY(this.value/this.max * 2 + 1.25);
    if(this.locationText){
      this.locationText.geometry = new THREE.TextGeometry((this.value + 2500) + "m", {font: this.UI.font, size: 0.05, height: 0.01});
      //this.locationText.computeBoundingBox();
    }
  }

};

module.exports = Gauge;<|endoftext|>


<commit_before>import Relay from 'react-relay';
import * as RelaySubscriptions from 'relay-subscriptions';

export default class AddTodoSubscription extends RelaySubscriptions.Subscription {
  static fragments = {
    viewer: () => Relay.QL`
    fragment on User {
      id
      totalCount
    }`,
  };
  getSubscription() {
    return Relay.QL`subscription {
      addTodoSubscription {
        todoEdge {
          node {
            id
            text
            complete
          }
        }
        viewer {
          id
          totalCount
        }
      }
    }`;
  }
  getVariables() {
    return {};
  }
  getConfigs() {
    return [{
      type: 'RANGE_ADD',
      parentName: 'viewer',
      parentID: this.props.viewer.id,
      connectionName: 'todos',
      edgeName: 'todoEdge',
      rangeBehaviors: () => 'append',
    }];
  }
}
<commit_msg>Add back __typename for new TodoEdge (#10)<commit_after>import Relay from 'react-relay';
import * as RelaySubscriptions from 'relay-subscriptions';

export default class AddTodoSubscription extends RelaySubscriptions.Subscription {
  static fragments = {
    viewer: () => Relay.QL`
    fragment on User {
      id
      totalCount
    }`,
  };
  getSubscription() {
    return Relay.QL`subscription {
      addTodoSubscription {
        todoEdge {
          __typename
          node {
            id
            text
            complete
          }
        }
        viewer {
          id
          totalCount
        }
      }
    }`;
  }
  getVariables() {
    return {};
  }
  getConfigs() {
    return [{
      type: 'RANGE_ADD',
      parentName: 'viewer',
      parentID: this.props.viewer.id,
      connectionName: 'todos',
      edgeName: 'todoEdge',
      rangeBehaviors: () => 'append',
    }];
  }
}
<|endoftext|>


<commit_before>import $ from 'jquery';

class Taxonomy {

  /**
   * Initialize Papi taxonomy class.
   */
  static init() {
    new Taxonomy().binds();
  }

  /**
   * Bind elements with functions.
   */
  binds() {
    $('#submit').on('click', this.addNewTerm.bind(this));
  }

  /**
   * Redirect if a new term is added and redirect is activated.
   *
   * @param {object} e
   */
  addNewTerm(e) {
    e.preventDefault();

    const $title    = $('#tag-name');
    const title     = $title.val();
    const $pageType = $('[data-papi-page-type-key=true]');

    if (!$pageType.data('redirect') && !$pageType.find(':selected').data('redirect')) {
      return;
    }

    if (!title.length) {
      return;
    }

    let interval;

    interval = setInterval(() => {
      if ($('#ajax-response').children().length) {
        clearInterval(interval);
        return;
      }

      const $thelist   = $('#the-list');
      const $rowTitles = $thelist.find('td.column-name a.row-title');
      const $rows      = $rowTitles.contents().filter(function () {
        return $(this).text().trim() === title.trim();
      });

      if ($rows.length) {
        clearInterval(interval);
        window.location = $rows[0].parentElement.href;
      }
    }, 500);
  }
}

export default Taxonomy;
<commit_msg>Add quotes to selectors<commit_after>import $ from 'jquery';

class Taxonomy {

  /**
   * Initialize Papi taxonomy class.
   */
  static init() {
    new Taxonomy().binds();
  }

  /**
   * Bind elements with functions.
   */
  binds() {
    $('#submit').on('click', this.addNewTerm.bind(this));
  }

  /**
   * Redirect if a new term is added and redirect is activated.
   *
   * @param {object} e
   */
  addNewTerm(e) {
    e.preventDefault();

    const $title    = $('#tag-name');
    const title     = $title.val();
    const $pageType = $('[data-papi-page-type-key="true"]');

    if (!$pageType.data('redirect') && !$pageType.find(':selected').data('redirect')) {
      return;
    }

    if (!title.length) {
      return;
    }

    let interval;

    interval = setInterval(() => {
      if ($('#ajax-response').children().length) {
        clearInterval(interval);
        return;
      }

      const $thelist   = $('#the-list');
      const $rowTitles = $thelist.find('td.column-name a.row-title');
      const $rows      = $rowTitles.contents().filter(function () {
        return $(this).text().trim() === title.trim();
      });

      if ($rows.length) {
        clearInterval(interval);
        window.location = $rows[0].parentElement.href;
      }
    }, 500);
  }
}

export default Taxonomy;
<|endoftext|>


<commit_before>var request = require("request"),
    Color = {
      RED: { hue: 0, saturation: 255 },
      GREEN: { hue: 25500, saturation: 255 }
    };

function Lightbulb(id, attr, router) {
  this.id = id;
  this.on = attr.state && attr.state.on;
  this.router = router;
}

Lightbulb.find = function(id, router, callback) {
  var url = router.url("lights/" + id);

  request.get({ url: url, json: true }, function(error, response, body) {
    if (error) {
      console.log("Error: couldn't fetch lightbulb with ID " + id);
      console.log(error);
      return;
    }

    var lightbulb = new Lightbulb(id, body, router);
    callback(lightbulb);
  });
};

Lightbulb.prototype.blinkRed = function() {
  this.setColor({
    color: Color.RED,
    blink: true
  });
};

Lightbulb.prototype.showGreen = function() {
  this.setColor({
    color: Color.GREEN,
    blink: false
  });
};

Lightbulb.prototype.setColor = function(options) {
  var url = this.router.url("lights/" + this.id + "/state"),
      color = options.color,
      payload = {
        on: this.on,
        hue: color.hue,
        sat: color.saturation
      };

  request.put({ url: url, json: payload }, function(error, response, body) {
    if (error) {
      console.log("Error: couldn't change lightbulb color");
      console.log(error);
    }
  });
};

module.exports = Lightbulb;
<commit_msg>Make the lightbulb blink when blink: true is passed into setColor<commit_after>var request = require("request"),
    blinkingDuration = 3,
    Color = {
      RED: { hue: 0, saturation: 255 },
      GREEN: { hue: 25500, saturation: 255 }
    };

function Lightbulb(id, attr, router) {
  this.id = id;
  this.on = attr.state && attr.state.on;
  this.router = router;
}

Lightbulb.find = function(id, router, callback) {
  var url = router.url("lights/" + id);

  request.get({ url: url, json: true }, function(error, response, body) {
    if (error) {
      console.log("Error: couldn't fetch lightbulb with ID " + id);
      console.log(error);
      return;
    }

    var lightbulb = new Lightbulb(id, body, router);
    callback(lightbulb);
  });
};

Lightbulb.prototype.blinkRed = function() {
  this.setColor({
    color: Color.RED,
    blink: true
  });
};

Lightbulb.prototype.showGreen = function() {
  this.setColor({
    color: Color.GREEN,
    blink: false
  });
};

Lightbulb.prototype.setColor = function(options) {
  var url = this.router.url("lights/" + this.id + "/state"),
      color = options.color,
      blink = options.blink,
      payload = {
        on: this.on,
        hue: color.hue,
        sat: color.saturation,
        alert: blink ? "lselect" : "none"
      },
      stopBlinking = this.stopBlinking.bind(this);

  request.put({ url: url, json: payload }, function(error, response, body) {
    if (error) {
      console.log("Error: couldn't set lightbulb color");
      console.log(error);
      return;
    }

    if (blink) {
      setTimeout(stopBlinking, blinkingDuration * 1000, color);
    }
  });
};

Lightbulb.prototype.stopBlinking = function(color) {
  this.setColor({
    color: color,
    blink: false
  });
};

module.exports = Lightbulb;
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/locale",
    "firebug/lib/dom",
    "firebug/lib/events",
    "firebug/chrome/module",
    "firebug/chrome/menu",
],
function(Firebug, FBTrace, Obj, Locale, Dom, Events, Module, Menu) {

"use strict";

// ********************************************************************************************* //
// Constants

var Cc = Components.classes;
var Ci = Components.interfaces;

var MAX_HISTORY_MENU_ITEMS = 15;

// Standard tracing output
var Trace = FBTrace.to("DBG_HISTORY");
var TraceError = FBTrace.toError();

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

/**
 * @module Support for back and forward navigation within Firebug UI. The logic allows to
 * go back over selected (main) panels history as well as over location changes in a panel.
 * The UI is composed from two buttons back and forward, which are presented in the main
 * Firebug toolbar.
 *
 * In order to record the history of selected panels and locations, there are two
 * events handled:
 *
 * 1) selectPanel: fired when a panel is selected
 * 2) navigate: executed when panel navigation happens
 */
var NavigationHistory = Obj.extend(Module,
/** @lends NavigationHistory */
{
    dispatchName: "navigationHistory",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Initialization

    initialize: function()
    {
        Module.initialize.apply(this, arguments);

        this.onSelectPanel = this.onSelectPanel.bind(this);

        var panelBar = getPanelBar();
        Events.addEventListener(panelBar, "selectPanel", this.onSelectPanel, false);
    },

    shutdown: function()
    {
        Module.shutdown.apply(this, arguments);

        var panelBar = getPanelBar();
        Events.removeEventListener(panelBar, "selectPanel", this.onSelectPanel, false);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Context

    initContext: function(context, persistedState)
    {
        Module.initContext.apply(this, arguments);

        // Initialize context members. The history is stored within
        // the current context (document).
        context.navigationHistory = [];
        context.navigationHistoryIndex = 0;

        if (persistedState && persistedState.navigationHistory)
        {
            context.navigationHistory = persistedState.navigationHistory;
            context.navigationHistoryIndex = persistedState.navigationHistoryIndex;
        }
    },

    destroyContext: function(context, persistedState)
    {
        Module.destroyContext.apply(this, arguments);

        if (persistedState)
        {
            persistedState.navigationHistory = context.navigationHistory;
            persistedState.navigationHistoryIndex = context.navigationHistoryIndex;
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // History popup menu

    onPopupShowing: function(popup, context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.onPopupShowing; " + currIndex + ", " +
            context.getName(), context);

        Dom.eraseNode(popup);

        var list = this.getHistory(context);

        // Don't display the popup for a single item.
        var count = list.length;
        if (count <= 1)
            return false;

        var maxItems = MAX_HISTORY_MENU_ITEMS;
        var half = Math.floor(maxItems / 2);
        var start = Math.max(currIndex - half, 0);
        var end = Math.min(start == 0 ? maxItems : currIndex + half + 1, count);

        if (end == count)
            start = Math.max(count - maxItems, 0);

        var tooltipBack = Locale.$STR("firebug.history.Go back to this panel");
        var tooltipCurrent = Locale.$STR("firebug.history.Stay on this panel");
        var tooltipForward = Locale.$STR("firebug.history.Go forward to this panel");

        for (var i = end - 1; i >= start; i--)
        {
            var historyItem = list[i];
            var panelType = Firebug.getPanelType(historyItem.panelName);
            var label = Firebug.getPanelTitle(panelType);

            if (historyItem.location && historyItem.location.url)
                label += " - " + historyItem.location.url;

            var menuInfo = {
                label: label,
                nol10n: true,
                className: "menuitem-iconic fbURLMenuItem",
            };

            if (i < currIndex)
            {
                menuInfo.className += " navigationHistoryMenuItemBack";
                menuInfo.tooltiptext = tooltipBack;
            }
            else if (i == currIndex)
            {
                menuInfo.type = "radio";
                menuInfo.checked = "true";
                menuInfo.className = "navigationHistoryMenuItemCurrent";
                menuInfo.tooltiptext = tooltipCurrent;
            }
            else
            {
                menuInfo.className += " navigationHistoryMenuItemForward";
                menuInfo.tooltiptext = tooltipForward;
            }

            var menuItem = Menu.createMenuItem(popup, menuInfo);
            menuItem.repObject = location;
            menuItem.setAttribute("index", i);
        }

        return true;
    },

    onHistoryCommand: function(event, context)
    {
        var menuItem = event.target;
        var index = menuItem.getAttribute("index");
        if (!index)
            return false;

        this.gotoHistoryIndex(context, index);
        return true;
    },

    goBack: function(context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.goBack; " + currIndex + ", " +
            context.getName(), context);

        this.gotoHistoryIndex(context, currIndex - 1);
    },

    goForward: function(context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.goForward; " + currIndex + ", " +
            context.getName(), context);

        this.gotoHistoryIndex(context, currIndex + 1);
    },

    gotoHistoryIndex: function(context, index)
    {
        var list = this.getHistory(context);
        if (index < 0 || index >= list.length)
            return;

        var historyItem = list[index];

        try
        {
            this.navInProgress = true;
            Firebug.chrome.navigate(historyItem.location, historyItem.panelName);
            context.navigationHistoryIndex = index;
        }
        catch (e)
        {
        }
        finally
        {
            this.navInProgress = false;
        }

        this.updateButtons(context);
    },

    updateButtons: function(context)
    {
        var list = this.getHistory(context);

        var backButton = Firebug.chrome.$("fbNavigateBackButton");
        var forwardButton = Firebug.chrome.$("fbNavigateForwardButton");

        backButton.setAttribute("disabled", "true");
        forwardButton.setAttribute("disabled", "true");

        if (list.length <= 1)
            return;

        var currIndex = this.getCurrentIndex(context);

        if (currIndex > 0)
            backButton.removeAttribute("disabled");

        if (currIndex < list.length-1)
            forwardButton.removeAttribute("disabled");
    },

    getHistory: function(context)
    {
        if (!context.navigationHistory)
            context.navigationHistory = [];

        return context.navigationHistory;
    },

    getCurrentIndex: function(context)
    {
        if (typeof(context.navigationHistoryIndex) == "undefined")
            context.navigationHistoryIndex = 0;

        return context.navigationHistoryIndex;
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // UI Listener

    onPanelNavigate: function(location, panel, panelName)
    {
        // The "panel" argument can be null in case of disabled panel.
        var panelName = (panel ? panel.name : panelName);
        if (!panelName)
        {
            TraceError.sysout("navigationHistory.onPanelNavigate; ERROR no panel name!");
            return;
        }

        var url = (location ? location.href : "No Location");
        var context = panel ? panel.context : Firebug.currentContext;
        var currIndex = this.getCurrentIndex(context);
        var list = this.getHistory(context);

        // Ignore side panel navigation.
        if (panel && panel.parentPanel)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore side panels");
            return;
        }

        // The user is navigating using the history UI, this action doesn't affect
        // the history list.
        if (this.navInProgress)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; navigation in progress");
            return;
        }

        // If the last item in the history is the same bail out.
        var lastHistoryItem = list.length ? list[list.length-1] : null;
        if (lastHistoryItem && lastHistoryItem.panelName == panelName &&
            lastHistoryItem.location == location)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore the same navigations", {
                lastHistoryItem: lastHistoryItem,
                panelName: panelName,
                location: location,
            });

            return;
        }

        // If the panel is the same, bail out.
        var currHistoryItem = list.length ? list[currIndex] : null;
        if (currHistoryItem && currHistoryItem.panelName == panelName &&
            currHistoryItem.location == location)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore the same panel navigation");
            return;
        }

        // Remove forward history.
        list.splice(currIndex + 1, list.length - (currIndex + 1));

        // New history record.
        list.push({panelName: panelName, location: location});
        context.navigationHistoryIndex = list.length - 1;

        Trace.sysout("navigationHistory.onPanelNavigate; New record created, total: " +
            list.length + ", " + panelName + ", " + (location ? location.url : "No Location"),
            list);

        // Update back and forward buttons in the UI.
        this.updateButtons(context);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Chrome Listener

    onSelectPanel: function(event)
    {
        var panelBar = getPanelBar();

        var panel = panelBar.selectedPanel;
        var tab = panelBar.selectedTab;
        var panelName = tab.panelType.prototype.name;
        var location = panel ? panel.location : null;

        Trace.sysout("navigationHistory.onSelectPanel; name: " +
            (panel ? panel.name : "unknown panel") + ", location: " +
            (panel ? panel.location : "unknown location") + ", tab name: " +
            (tab ? tab.panelType.prototype.name : "unknown tab name"));

        this.onPanelNavigate(location, panel, panelName);
    },
});

// ********************************************************************************************* //
// Private Local Helpers

function getPanelBar()
{
    return Firebug.chrome.getElementById("fbPanelBar1");
}

// ********************************************************************************************* //
// Registration

Firebug.registerModule(NavigationHistory);
Firebug.registerUIListener(NavigationHistory);

// Expose for XUL UI
Firebug.NavigationHistory = NavigationHistory;

return NavigationHistory;

// ********************************************************************************************* //
});
<commit_msg>Avoid NPE<commit_after>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/locale",
    "firebug/lib/dom",
    "firebug/lib/events",
    "firebug/chrome/module",
    "firebug/chrome/menu",
],
function(Firebug, FBTrace, Obj, Locale, Dom, Events, Module, Menu) {

"use strict";

// ********************************************************************************************* //
// Constants

var Cc = Components.classes;
var Ci = Components.interfaces;

var MAX_HISTORY_MENU_ITEMS = 15;

// Standard tracing output
var Trace = FBTrace.to("DBG_HISTORY");
var TraceError = FBTrace.toError();

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

/**
 * @module Support for back and forward navigation within Firebug UI. The logic allows to
 * go back over selected (main) panels history as well as over location changes in a panel.
 * The UI is composed from two buttons back and forward, which are presented in the main
 * Firebug toolbar.
 *
 * In order to record the history of selected panels and locations, there are two
 * events handled:
 *
 * 1) selectPanel: fired when a panel is selected
 * 2) navigate: executed when panel navigation happens
 */
var NavigationHistory = Obj.extend(Module,
/** @lends NavigationHistory */
{
    dispatchName: "navigationHistory",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Initialization

    initialize: function()
    {
        Module.initialize.apply(this, arguments);

        this.onSelectPanel = this.onSelectPanel.bind(this);

        var panelBar = getPanelBar();
        Events.addEventListener(panelBar, "selectPanel", this.onSelectPanel, false);
    },

    shutdown: function()
    {
        Module.shutdown.apply(this, arguments);

        var panelBar = getPanelBar();
        Events.removeEventListener(panelBar, "selectPanel", this.onSelectPanel, false);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Context

    initContext: function(context, persistedState)
    {
        Module.initContext.apply(this, arguments);

        // Initialize context members. The history is stored within
        // the current context (document).
        context.navigationHistory = [];
        context.navigationHistoryIndex = 0;

        if (persistedState && persistedState.navigationHistory)
        {
            context.navigationHistory = persistedState.navigationHistory;
            context.navigationHistoryIndex = persistedState.navigationHistoryIndex;
        }
    },

    destroyContext: function(context, persistedState)
    {
        Module.destroyContext.apply(this, arguments);

        if (persistedState)
        {
            persistedState.navigationHistory = context.navigationHistory;
            persistedState.navigationHistoryIndex = context.navigationHistoryIndex;
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // History popup menu

    onPopupShowing: function(popup, context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.onPopupShowing; " + currIndex + ", " +
            context.getName(), context);

        Dom.eraseNode(popup);

        var list = this.getHistory(context);

        // Don't display the popup for a single item.
        var count = list.length;
        if (count <= 1)
            return false;

        var maxItems = MAX_HISTORY_MENU_ITEMS;
        var half = Math.floor(maxItems / 2);
        var start = Math.max(currIndex - half, 0);
        var end = Math.min(start == 0 ? maxItems : currIndex + half + 1, count);

        if (end == count)
            start = Math.max(count - maxItems, 0);

        var tooltipBack = Locale.$STR("firebug.history.Go back to this panel");
        var tooltipCurrent = Locale.$STR("firebug.history.Stay on this panel");
        var tooltipForward = Locale.$STR("firebug.history.Go forward to this panel");

        for (var i = end - 1; i >= start; i--)
        {
            var historyItem = list[i];
            var panelType = Firebug.getPanelType(historyItem.panelName);
            var label = Firebug.getPanelTitle(panelType);

            if (historyItem.location && historyItem.location.url)
                label += " - " + historyItem.location.url;

            var menuInfo = {
                label: label,
                nol10n: true,
                className: "menuitem-iconic fbURLMenuItem",
            };

            if (i < currIndex)
            {
                menuInfo.className += " navigationHistoryMenuItemBack";
                menuInfo.tooltiptext = tooltipBack;
            }
            else if (i == currIndex)
            {
                menuInfo.type = "radio";
                menuInfo.checked = "true";
                menuInfo.className = "navigationHistoryMenuItemCurrent";
                menuInfo.tooltiptext = tooltipCurrent;
            }
            else
            {
                menuInfo.className += " navigationHistoryMenuItemForward";
                menuInfo.tooltiptext = tooltipForward;
            }

            var menuItem = Menu.createMenuItem(popup, menuInfo);
            menuItem.repObject = location;
            menuItem.setAttribute("index", i);
        }

        return true;
    },

    onHistoryCommand: function(event, context)
    {
        var menuItem = event.target;
        var index = menuItem.getAttribute("index");
        if (!index)
            return false;

        this.gotoHistoryIndex(context, index);
        return true;
    },

    goBack: function(context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.goBack; " + currIndex + ", " +
            context.getName(), context);

        this.gotoHistoryIndex(context, currIndex - 1);
    },

    goForward: function(context)
    {
        var currIndex = this.getCurrentIndex(context);

        Trace.sysout("navigationHistory.goForward; " + currIndex + ", " +
            context.getName(), context);

        this.gotoHistoryIndex(context, currIndex + 1);
    },

    gotoHistoryIndex: function(context, index)
    {
        var list = this.getHistory(context);
        if (index < 0 || index >= list.length)
            return;

        var historyItem = list[index];

        try
        {
            this.navInProgress = true;
            Firebug.chrome.navigate(historyItem.location, historyItem.panelName);
            context.navigationHistoryIndex = index;
        }
        catch (e)
        {
        }
        finally
        {
            this.navInProgress = false;
        }

        this.updateButtons(context);
    },

    updateButtons: function(context)
    {
        var list = this.getHistory(context);

        var backButton = Firebug.chrome.$("fbNavigateBackButton");
        var forwardButton = Firebug.chrome.$("fbNavigateForwardButton");

        backButton.setAttribute("disabled", "true");
        forwardButton.setAttribute("disabled", "true");

        if (list.length <= 1)
            return;

        var currIndex = this.getCurrentIndex(context);

        if (currIndex > 0)
            backButton.removeAttribute("disabled");

        if (currIndex < list.length-1)
            forwardButton.removeAttribute("disabled");
    },

    getHistory: function(context)
    {
        if (!context.navigationHistory)
            context.navigationHistory = [];

        return context.navigationHistory;
    },

    getCurrentIndex: function(context)
    {
        if (typeof(context.navigationHistoryIndex) == "undefined")
            context.navigationHistoryIndex = 0;

        return context.navigationHistoryIndex;
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // UI Listener

    onPanelNavigate: function(location, panel, panelName)
    {
        // The "panel" argument can be null in case of disabled panel.
        var panelName = (panel ? panel.name : panelName);
        if (!panelName)
        {
            TraceError.sysout("navigationHistory.onPanelNavigate; ERROR no panel name!");
            return;
        }

        var url = (location ? location.href : "No Location");
        var context = panel ? panel.context : Firebug.currentContext;
        var currIndex = this.getCurrentIndex(context);
        var list = this.getHistory(context);

        // Ignore side panel navigation.
        if (panel && panel.parentPanel)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore side panels");
            return;
        }

        // The user is navigating using the history UI, this action doesn't affect
        // the history list.
        if (this.navInProgress)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; navigation in progress");
            return;
        }

        // If the last item in the history is the same bail out.
        var lastHistoryItem = list.length ? list[list.length-1] : null;
        if (lastHistoryItem && lastHistoryItem.panelName == panelName &&
            lastHistoryItem.location == location)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore the same navigations", {
                lastHistoryItem: lastHistoryItem,
                panelName: panelName,
                location: location,
            });

            return;
        }

        // If the panel is the same, bail out.
        var currHistoryItem = list.length ? list[currIndex] : null;
        if (currHistoryItem && currHistoryItem.panelName == panelName &&
            currHistoryItem.location == location)
        {
            Trace.sysout("navigationHistory.onPanelNavigate; ignore the same panel navigation");
            return;
        }

        // Remove forward history.
        list.splice(currIndex + 1, list.length - (currIndex + 1));

        // New history record.
        list.push({panelName: panelName, location: location});
        context.navigationHistoryIndex = list.length - 1;

        Trace.sysout("navigationHistory.onPanelNavigate; New record created, total: " +
            list.length + ", " + panelName + ", " + (location ? location.url : "No Location"),
            list);

        // Update back and forward buttons in the UI.
        this.updateButtons(context);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Chrome Listener

    onSelectPanel: function(event)
    {
        var panelBar = getPanelBar();

        var panel = panelBar.selectedPanel;
        var tab = panelBar.selectedTab;
        if (!tab)
            return;

        var panelName = tab.panelType.prototype.name;
        var location = panel ? panel.location : null;

        Trace.sysout("navigationHistory.onSelectPanel; name: " +
            (panel ? panel.name : "unknown panel") + ", location: " +
            (panel ? panel.location : "unknown location") + ", tab name: " +
            (tab ? tab.panelType.prototype.name : "unknown tab name"));

        this.onPanelNavigate(location, panel, panelName);
    },
});

// ********************************************************************************************* //
// Private Local Helpers

function getPanelBar()
{
    return Firebug.chrome.getElementById("fbPanelBar1");
}

// ********************************************************************************************* //
// Registration

Firebug.registerModule(NavigationHistory);
Firebug.registerUIListener(NavigationHistory);

// Expose for XUL UI
Firebug.NavigationHistory = NavigationHistory;

return NavigationHistory;

// ********************************************************************************************* //
});
<|endoftext|>


<commit_before>Template.initiativeCard.helpers({
  isMine: function(){
    return this.createdBy === Meteor.userId();
  },
  showStatus: function(){
    return Router.current().route.path(this).match('/profile/');
  },
  status: function(){
    return this.active ? 'Active': 'Inactive';
  }
});

Template.initiativeCard.events({
  'click .votes': function(e, tpl){
    // TODO: restrict votes to 1 pr initiative
    var initiative = this;
    addOrRemoveVote(initiative);

  },
  'dblclick .touch .card-image a': function(e, tpl){
    console.log('double click initiative');
    e.preventDefault();
    var initiative = this;
    addOrRemoveVote(initiative);
  },
  'click .status': function(e, tpl){
    Meteor.call('setInactiveActive', this, function(err, res){
      if(err)
        sAlert.error(err.message);

      sAlert.info('initiative updated');
    });
  }
});<commit_msg>Add else according to comment on #40<commit_after>Template.initiativeCard.helpers({
  isMine: function(){
    return this.createdBy === Meteor.userId();
  },
  showStatus: function(){
    return Router.current().route.path(this).match('/profile/');
  },
  status: function(){
    return this.active ? 'Active': 'Inactive';
  }
});

Template.initiativeCard.events({
  'click .votes': function(e, tpl){
    // TODO: restrict votes to 1 pr initiative
    var initiative = this;
    addOrRemoveVote(initiative);

  },
  'dblclick .touch .card-image a': function(e, tpl){
    console.log('double click initiative');
    e.preventDefault();
    var initiative = this;
    addOrRemoveVote(initiative);
  },
  'click .status': function(e, tpl){
    Meteor.call('setInactiveActive', this, function(err, res){
      if(err){
        sAlert.error(err.message);
      } else {
        sAlert.info('initiative updated');
      }
    });
  }
});<|endoftext|>