var imageRender = require('./image-render') module.exports = function DeviceScreenDirective($document, ScalingService, $rootScope) { return { restrict: 'E', template: require('./screen.jade'), link: function (scope, element, attrs) { scope.device.promise.then(function(device) { var loader = new Image() , canvas = element.find('canvas')[0] , finger = element.find('span') , input = element.find('textarea') , g = canvas.getContext('2d') , displayWidth = 0 , displayHeight = 0 , scaler = ScalingService.coordinator( device.display.width , device.display.height ) , cached = { displayWidth: 0, displayHeight: 0, canvasStyleWidth: 0, canvasStyleHeight: 0, imageWidth: 0, imageHeight: 0 } $rootScope.$on('pageHidden', function () { scope.canView = false }) $rootScope.$on('pageVisible', function () { scope.canView = true }) scope.$watch('canView', function (val) { if (val) { loadScreen() } else { scope.fps = null //clearCanvas() } }) scope.$watch('showScreen', function (val) { if (val) { loadScreen(); } else { scope.fps = null //clearCanvas(); } }) function updateDisplaySize() { displayWidth = element[0].offsetWidth displayHeight = element[0].offsetHeight // Developer error, let's try to reduce debug time if (!displayWidth || !displayHeight) { throw new Error( 'Unable to update display size; container must have dimensions' ) } } function loadScreen() { loader.src = device.display.url + '?width=' + displayWidth + '&height=' + displayHeight + '&time=' + Date.now() } loader.onload = function () { if (scope.canView && scope.showScreen) { // Sets the size only if updated if (cached.displayWidth !== displayWidth || cached.displayHeight !== displayHeight || cached.imageWidth !== this.width || cached.imageHeight !== this.height ) { cached.displayWidth = displayWidth cached.displayHeight = displayHeight cached.imageWidth = this.width cached.imageHeight = this.height var size = scaler.projectedSize(displayWidth, displayHeight) // Make sure we're rendering pixels 1 to 1 canvas.width = this.width canvas.height = this.height // Perhaps we have a massive screen but not enough pixels. Let's // scale up canvas.style.width = size.width + 'px' canvas.style.height = size.height + 'px' } // Draw the image g.drawImage(this, 0, 0) // Reset error, if any if (scope.displayError) { scope.$apply(function () { scope.displayError = false }) } // Next please loadScreen() } else { console.log('Nothing to show') } } loader.onerror = function () { scope.$apply(function () { scope.displayError = true }) } function sendTouch(type, e) { var scaled = scaler.coords( displayWidth , displayHeight , e.offsetX , e.offsetY ) finger[0].style.webkitTransform = 'translate3d(' + e.offsetX + 'px,' + e.offsetY + 'px,0)' scope.control[type]( scaled.xP * device.display.width , scaled.yP * device.display.height ) } function downListener(e) { e.preventDefault() input[0].focus() element.addClass('fingering') sendTouch('touchDown', e) element.bind('mousemove', moveListener) $document.bind('mouseup', upListener) $document.bind('mouseleave', upListener) } function moveListener(e) { sendTouch('touchMove', e) } function upListener(e) { sendTouch('touchUp', e) stop() } function stop() { element.removeClass('fingering') element.unbind('mousemove', moveListener) $document.unbind('mouseup', upListener) $document.unbind('mouseleave', upListener) } scope.$on('$destroy', function () { loader.onload = loader.onerror = null stop() }) input.bind('keydown', function (e) { scope.control.keyDown(e.keyCode) }) input.bind('keyup', function (e) { scope.control.keyUp(e.keyCode) }) input.bind('keypress', function (e) { e.preventDefault() // no need to change value scope.control.type(String.fromCharCode(e.charCode)) }) input.bind('paste', function (e) { e.preventDefault() // no need to change value scope.control.type(e.clipboardData.getData('text/plain')) }) element.bind('mousedown', downListener) updateDisplaySize() loadScreen() }) } } }