(function() { /* TODO(sissel): This could use some serious refactoring. */ $(document).ready(function() { var state = { x: -1, y: -1, moving: false, dragging: false, width: window.innerWidth, height: window.innerHeight, key: undefined, } var status = $("#status"); /* Changing orientation sometimes leaves the viewport * not starting at 0,0. Fix it with this hack. * Also, we want to make the content size full height. */ $(window).bind("orientationchange resize pageshow", function(event) { scroll(0, 0); console.log(window.orientation); var header = $(".header:visible"); var footer = $(".footer:visible"); var content = $(".content:visible"); var viewport_height = $(window).height(); var content_height = viewport_height - header.outerHeight() - footer.outerHeight(); /* Trim margin/border/padding height */ content_height -= (content.outerHeight() - content.height()); content.height(content_height); }); var connect = function(state) { status.html("connecting..."); var websocket = new WebSocket("ws://" + document.location.hostname + ":5001"); websocket.onopen = function(event) { status.html("websocket ready"); } websocket.onclose = function(event) { status.html("Closed, trying to reopen."); setTimeout(function() { connect(state); }, 1000); } state.websocket = websocket; } connect(state); /* This will track orientation/motion changes with the accelerometer and * gyroscope. Not sure how useful this would be... */ //$(window).bind("devicemotion", function(event) { //var e = event.originalEvent; //state.accel = e.accelerationIncludingGravity; /* Trim shakes */ //if (Math.abs(state.accel.x) < 0.22 && Math.abs(state.accel.y) < 0.22) { //return; //} //status.html("Motion: \nx: " + state.accel.x + "\ny: " + state.accel.y + "\nz: " + state.accel.z); //state.websocket.send(JSON.stringify({ //action: "move", //rel_x: Math.ceil(state.accel.x) * -1, //rel_y: Math.ceil(state.accel.y) * -1, //})); //}); $("#area").bind("touchstart", function(event) { event.preventDefault(); var e = event.originalEvent; var touches = e.touches; var output = "Start: " + touches[0].clientX + "," + touches[0].clientY + "\n"; output += "Fingers: " + touches.length + "\n"; status.html(output); /* number of fingers == mouse button */ state.fingers = touches.length; switch (state.fingers) { case 1: state.button = 1; break; case 2: state.button = 3; break; case 3: state.button = 2; break; } var now = (new Date()).getTime(); if ((now - state.last_click) < 170) { /* Start dragging */ state.websocket.send(JSON.stringify({ action: "mousedown", button: state.button, })) state.dragging = true; } }).bind("touchend", function(event) { /* $("#area").bind("touchend" ... */ var e = event.originalEvent; var touches = e.touches; if (state.dragging) { state.websocket.send(JSON.stringify({ action: "mouseup", button: state.button, })); state.dragging = false; } else { if (state.moving) { var e = state.last_move; var r = e.rotation; if (r < 0) { r += 360; } status.html(r); if (r > 75 && r < 105) { /* Activate the keyboard when there's a 90-dgree rotation*/ var keyboard = $(""); keyboard.css("width", "100%"); keyboard.css("height", "100%"); status.html(""); keyboard.appendTo(status).focus(); keyboard.bind("keypress", function(event) { var e = event.originalEvent; var key = e.charCode; console.log(key); if (!key) { key = (e.keyCode ? e.keyCode : e.which); } state.websocket.send(JSON.stringify({ action: "log", shift: e.shiftKey, char: e.charCode, ctrl: e.ctrlKey, meta: e.ctrlKey, })); state.websocket.send(JSON.stringify({ action: "keypress", key: key, shift: e.shiftKey, })); e.preventDefault(); }).bind("change", function(event) { /* Skip empty changes */ if (keyboard.val() == "") { return; } state.websocket.send(JSON.stringify({ action: "type", string: keyboard.val(), })); /* Clear the field */ keyboard.val(""); }); keyboard.bind("keyup", function(event) { var e = event.originalEvent; state.websocket.send(JSON.stringify({ action: "log", shift: e.shiftKey, char: e.charCode, key: e.which, ctrl: e.ctrlKey, meta: e.ctrlKey, })); console.log(key); var key = (e.keyCode ? e.keyCode : e.which); if (key >= 32 && key <= 127) { /* skip printable keys (a-z, etc) */ return; } state.websocket.send(JSON.stringify({ action: "keypress", key: key, shift: e.shiftKey, })); e.preventDefault(); }); //status.html(""); //$("#keyboard").focus(); } } else { /* No movement, click! */ status.html("Click!"); state.websocket.send(JSON.stringify({ action: "click", button: state.button, })); state.last_click = (new Date()).getTime(); } } state.moving = false; event.preventDefault(); }).bind("touchmove", function(event) { /* $("#area").bind("touchmove" ... */ var e = event.originalEvent; var touches = e.touches; event.preventDefault(); if (!state.moving) { /* Start calculating delta offsets now */ state.moving = true; state.x = touches[0].clientX; state.y = touches[0].clientY; /* Skip this event */ return; } state.last_move = e; var output = ""; for (var i in touches) { output += i + ": " + touches[i].clientX + "," + touches[i].clientY + "\n"; } var r = e.rotation; if (r < 0) { r += 360; } output += "rotation: " + r + "\n"; output += "scale: " + e.scale + "\n"; x = touches[0].clientX; y = touches[0].clientY; delta_x = (x - state.x); delta_y = (y - state.y); /* Apply acceleration */ sign_x = (delta_x < 0 ? -1 : 1); sign_y = (delta_y < 0 ? -1 : 1); delta_x = Math.ceil(Math.pow(Math.abs(delta_x), 1.5) * sign_x); delta_y = Math.ceil(Math.pow(Math.abs(delta_y), 1.5) * sign_y); output += "Delta: " + delta_x + ", " + delta_y + "\n"; status.html(output); state.x = x; state.y = y; if (e.rotation < -10 || e.rotation > 10) { /* Skip rotations that are probably not mouse-cursor-wanting movements */ return; } if (e.scale < 0.9 || e.scale > 1.1) { /* Skip scales that are probably not mouse-cursor-wanting movements */ return; } if (touches.length > 1 && !state.dragging) { /* Multifinger movement, probably should scroll? */ if (delta_y < 0 || delta_y > 0) { /* Scroll */ state.websocket.send(JSON.stringify({ action: "click", button: (delta_y < 0) ? 4 : 5, })) } } else { state.websocket.send(JSON.stringify({ action: "mousemove_relative", rel_x: delta_x, rel_y: delta_y })); } }); /* $("#area").bind( ... )*/ /* Take commands like this: * * Key press: * * * Mouse click * */ $("a.command").bind("touchstart", function(event) { //event.preventDefault(); state.touchelement = this; }).bind("touchmove", function(event) { event.preventDefault(); }).bind("touchend", function(event) { //event.preventDefault(); console.log(this) if (state.touchelement == this) { console.log(this) state.websocket.send(JSON.stringify({ action: $(this).attr("data-action"), key: $(this).attr("data-key"), button: $(this).attr("data-button"), })); } }); }); /* $(document).ready */ })();