Web workers and Canvas data - javascript

I have seen a lot of threads about web workers and <canvas> data passing, and I'm not sure if my scenario is implementable.
I want to create a small site for users to learn to code in Javascript. When users click a button, the code is run in a web worker. To help them, I have also created methods for "printing" (which basically just adds text to a <pre> element.
// get code from user and prepend helper "functions"
var userCode = editor.getValue();
var codeWithMessages = "\n\
function print(data) { postMessage(\"\"+data); } \n\
function println(data) { postMessage(\"\"+data+\'\\n\'); } \n\
function alert(data) { postMessage('ALERT'+data); } \n\
\n" + userCode;
var codeWithMessagesAndExit = codeWithMessages + "\npostMessage('exit()');";
var blob = new Blob([codeWithMessagesAndExit], {type: 'application/javascript'});
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
outer.worker = new Worker(blobURL);
...
// handle messages by "printing" to the run-output element, or display
// a success message when finishing
outer.worker.addEventListener('message', function (event) {
if (event.data == "exit()") {
outer.worker.terminate();
outer.worker = null;
outer.codeRunStatus = outer.CODE_RUN_SUCCESS;
outer.errorMessage = null;
outer.outputFromLatestRun = $("#run-output").text();
$("#run-output").append("<span class='code-run-success'>\nKörning klar</span>");
enableButtons();
}
else if (event.data.indexOf("ALERT") == 0) {
alert(event.data.substring(5));
}
else {
$("#run-output").append(event.data);
}
}, false);
// start the worker
outer.worker.postMessage();
Now I want to add a canvas to the page, so users could write code to draw on it.
var canvas = document.getElementById("user-canvas");
var ctx = canvas.getContext("2d");
var imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
// rest same as above
outer.worker.postMessage(imgData);
I don't know how to proceed from here. Ideally the users could write something like
myCanvas.fillStyle = "rgb(200,0,0)";
myCanvas.fillRect (10, 10, 55, 50);
and then have this processed by the event listener like I did with my print() functions. Is this possible?

DOM can't be accessed from a WebWorker.
The best way I can see is to re-define this object in the webworker, and define a protocol to transmit each call to a method. But it won't work when you need other objects like images.
Worker-side :
var CanvasRenderingContext2D = function() {
this.fillStyle = "black";
this.strokeStyle = "black";
...
this.lineWidth = 1.0;
};
["fillRect", "strokeRect", "beginPath", ... "rotate", "stroke"].forEach(function(methodName) {
CanvasRenderingContext2D.prototype[methodName] = function() {
postMessage({called: methodName, args: arguments, currentObjectAttributes: this});
};
});
...
var myCanvas = new CanvasRenderingContext2D();
myCanvas.fillStyle = "rgb(200,0,0)";
myCanvas.fillRect(10, 10, 55, 50);
Main-page side :
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var worker = new Worker( ... );
worker.onMessage = function(event) {
var data = event.data;
// Refreshing context attributes
var attributes = data.currentObjectAttributes;
for(var k in attributes) {
context[k] = attributes[k];
}
// Calling method
var method = context[data.called];
method.apply(context, data.args);
};
EDIT :
I tried to integrate it with your code (not tested). To integrate it, I had to change the structure of the messages sent by the worker.
// get code from user and prepend helper "functions"
var userCode = editor.getValue();
var codeWithMessages = '\n\
function print (data) { postMessage(["print", data.toString()]); } \n\
function println(data) { postMessage(["print", data.toString() + "\\n"]); } \n\
function alert (data) { postMessage(["alert", data.toString()]); } \n\
var CanvasRenderingContext2D = function() { \n\
this.fillStyle = "black"; \n\
this.strokeStyle = "black"; \n\
/* ... */ \n\
this.lineWidth = 1.0; \n\
}; \n\
["fillRect", "strokeRect", "beginPath", /* ... */ "rotate", "stroke"].forEach(function(methodName) { \n\
CanvasRenderingContext2D.prototype[methodName] = function() { \n\
postMessage(["canvas", {called: methodName, args: Array.prototype.slice.call(arguments), currentObjectAttributes: this}]); \n\
}; \n\
});\n' + userCode;
var codeWithMessagesAndExit = codeWithMessages + "\npostMessage(['exit']);";
var blob = new Blob([codeWithMessagesAndExit], {type: 'application/javascript'});
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
outer.worker = new Worker(blobURL);
...
// Define your canvas ...
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
// handle messages by "printing" to the run-output element, or display
// a success message when finishing
outer.worker.addEventListener('message', function (event) {
var method = event.data[0] || null;
var data = event.data[1] || null;
if(method == "canvas") {
// Refreshing context attributes
var attributes = data.currentObjectAttributes;
for(var k in attributes) {
context[k] = attributes[k];
}
// Calling method
var method = context[data.called];
method.apply(context, data.args);
} else if(method == "exit") {
outer.worker.terminate();
outer.worker = null;
outer.codeRunStatus = outer.CODE_RUN_SUCCESS;
outer.errorMessage = null;
outer.outputFromLatestRun = $("#run-output").text();
$("#run-output").append("<span class='code-run-success'>\nKörning klar</span>");
enableButtons();
} else if(method == "alert") {
alert(data);
} else if(method == "print") {
$("#run-output").append(data);
} else {
$("#run-output").append(event.data);
}
}, false);
// start the worker
outer.worker.postMessage();

Related

What is wrong with my JS webassemblity player?

I am trying to port a C++ program to WASM using emscripten.
The compilation process has been mastered, but so far with the presentation, which is bad ... I have
problem:
Uncaught ReferenceError: request is not defined
request.onload = function() {
Here is my script:
<script type='text/javascript'>
request.onload = function() {
var bytes = request.response;
fetch('hello.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
// Do something with the results!
console.log(results);
});
};
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&");
//text = text.replace(/</g, "<");
//text = text.replace(/>/g, ">");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
canvas: (function() {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.last.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
Module.setStatus.last.time = now;
Module.setStatus.last.text = text;
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
</script>
(updated: right code) here is my source of testing site:
https://www.dropbox.com/sh/elgdplx8xmvp51g/AAC-M0oCrA0_rgWZfrRvMt8na?dl=0 look at hello.html
Unfortunately request is not a "standard variable of connection" and is not special in any way. What you probably want is window.onload which is a global event handler available on the window object.
window is a special variable and does have the onload event handler available.
Take a look at the documentation for onload
<script type='text/javascript'>
window.onload = function() {
var bytes = request.response;
fetch('hello.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
// Do something with the results!
console.log(results);
});
};
// Rest of your code ...
Finally a have successfuly build the program and my script now looking just only.
<script src=./a.out.js>
I have update files on my dropbox-link to test project folder for more info. https://www.dropbox.com/sh/elgdplx8xmvp51g/AAC-M0oCrA0_rgWZfrRvMt8na?dl=0
In two words it separate script for two parts in the ending of html page
1st is
<script type='text/javascript'>
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&");
//text = text.replace(/</g, "<");
//text = text.replace(/>/g, ">");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
if (0) { // XXX disabled for safety typeof dump == 'function') {
dump(text + '\n'); // fast, straight to the real console
} else {
console.error(text);
}
},
canvas: (function() {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
</script>
and the second one is just
<script src=./a.out.js>
full of text you cant see on link to dropbox? its a lot of code to post here
and 3rd this is that i have copy from emscripter git repo html document that it must generate (but in my way not) and also put it to drop box link, to not to spam here.

checking image dimensions before ajax post event in javascript

I am attempting to access the dimensions from my uploaded image before I post it to the post upload endpoint. If you look, there is a variable issueArrived that is supposed to determine if the image is too small and if so negate the upload process. Unfortunately, the image doesn't access the dimensions check until after the upload to the server commences. Any help would be appreciated.
// internal function that creates an input element
var file = newElement("input", 0, "");
// sets the input element as type file
file.type = "file";
file.multiple = "multiple";
file.name = "photoupload[]";
file.accept = "image/*";
var issueArrived = false;
file.onchange = function(e) {
// internal function that creates an image element
var img = newElement("img", 0, "");
img.onload = function(){
var cw = img.width;
var ch = img.height;
if(cw < 500 || ch < 500) {
alert("Photo must be atleast 500x500");
issueArrived = true;
return false;
}
}
img.src = URL.createObjectURL(this);
if (issueArrived) return;
var formdata = new FormData();
formdata.append("photoupload[]", this);
var x = new XMLHttpRequest();
x.open("POST", "/media/uploadphotos", true);
x.send(formdata);
}
file.click();
onchange method is async. You can't expect to set the value from issueArrived inside it an access it outside.
You can rewrite this way:
file.onchange=function(e){
// internal function that creates an image element
var img=newElement("img",0,"");
img.onload=function(){
var cw=img.width;
var ch=img.height;
if(cw<500||ch<500){
alert("Photo must be atleast 500x500");
} else {
var formdata=new FormData();
formdata.append("photoupload[]",this);
var x=new XMLHttpRequest();
x.open("POST","/media/uploadphotos",true);
x.send(formdata);
}
}
img.src=URL.createObjectURL(this);
}
file.click();
or, better, you can create a function that gets the file and returns a promise.
function checkSize(fileToCheck) {
return new Promise( function(resolve, reject) {
var img = newElement("img",0,"");
img.onload=function(){
var cw=img.width;
var ch=img.height;
cw<500||ch<500 ? reject() : resolve()
}
img.src=URL.createObjectURL(fileToCheck);
})
}
...
file.onchange=function(e){
checkSize(this)
.then( function() { /* success handler */ } )
.catch( function() { /* error handler */ } )
}

how to pause and resume voice recording in android using cordova media plugin

I'm using angularjs in visual studio.using cordova media plugin startRecord() and stopRecord() is working but not able to pause and resume recording.I'm not using media capture plugin as i don't have default recorder installed.
This is my code:
var audurl = '///storage/emulated/0/New/';
audurl += 'Voice_' + '.amr';
var mediaRec;
function recordAudio() {
mediaRec = new Media(audurl, onSuccess, onError);
mediaRec.startRecord();
}
function pauseAudio() {
mediaRec = new Media(audurl, onSuccess, onError);
mediaRec.pauseRecord();
}
thanks...
On my phone the method media.resumeRecord was not available, although in this soure-code it is defined. Nevertheless you can take advantage of all other methods, like startRecord and stopRecord, to rebuild a kind of resumeRecord function, as it is done in a handler below:
var myRecordHandler = function () {
// ALL RECORDED FILES ARE SAVED IN THIS ARRAY
var recordedAudioFiles = [];
// REMEMBER POSITION WHEN PLAYING IS STOPPED
var currentPosition = {index:0,shift:0};
// PAUSE-MODE
var paused = false;
// SET A SPECIFC DIRECTORY WHERE THE FILES ARE STORED INTO
// DEFAULT: ''
this.setDirectory = function(dir) {this.dir=dir;};
// SET FILENAME
// DEFAULT: recoredFilesX
this.setFilename = function(filename) {this.filename=filename;};
// SET MIME/Type of THE FILES;
// DEFAULT: mp3
this.setFileType = function(type) {this.filetype=type;};
// GET ALL RECORED FILES
this.getAllFiles = function() {return recordedAudioFiles;};
// STOP/PAUSE RECORDED FILES
var handleRecordedFileHold = function () {
for (var r = 0; r < recordedAudioFiles.length; r++) {
var recordedAudioFile = recordedAudioFiles[r];
if(recordedAudioFile.isBeingRecorded){
if(paused)recordedAudioFile.media.pause();
else recordedAudioFile.media.stop();
continue;
}
recordedAudioFile.duration = new Date().getTime() - recordedAudioFile.startTime;
// call release to free this created file so that it could get deleted for instance
recordedAudioFile.media.stopRecord();
recordedAudioFile.media.release();
recordedAudioFile.isBeingRecorded = true;
}
}
// START RECORDING
this.startAudioRecording = function() {
paused = false;
handleRecordedFileHold();
var dir = this.dir ? this.dir : '';
var filename = this.filename ? this.filename : 'recoredFiles';
var type = this.filetype ? this.filetype : 'mp3';
var src = dir + filename + (recordedAudioFiles.length + 1) + '.' + type;
var mediaRec = new Media(src,
function () {
console.log('recordAudio():Audio Success');
},
function (err) {
console.log('recordAudio():Audio Error: ' + err.code);
});
recordedAudioFiles.push({
media: mediaRec,
startTime: new Date().getTime()
});
mediaRec.startRecord();
}
// PAUSE RECORDING
this.pauseRecoredFiles = function () {
if(recordedAudioFiles.length){
paused = true;
clearTimeout(currentPosition.timeout);
handleRecordedFileHold();
var recoredMedia = recordedAudioFiles[currentPosition.index].media;
recoredMedia.getCurrentPosition(
function (position) {
currentPosition.shift = position;
},
function (e) {
console.log("Error getting pos=" + e);
}
);
}
}
// PLAY RECORD
this.playRecordedFiles = function () {
handleRecordedFileHold();
var playNextFile = function () {
var recoredMedia = recordedAudioFiles[currentPosition.index];
if (recoredMedia) {
if(paused){
recoredMedia.media.seekTo(currentPosition.shift*1000);
paused = false;
}
recoredMedia.media.play();
currentPosition.timeout = setTimeout(function () {
currentPosition.index++;
recoredMedia.media.stop();
playNextFile();
}, recoredMedia.duration ? recoredMedia.duration : 0);
}
else{
paused = false;
currentPosition.index = currentPosition.shift = 0;
}
};
playNextFile();
}
// RESET PLAY
this.stopRecordedFiles = function () {
currentPosition.index = currentPosition.shift = 0;
clearTimeout(currentPosition.timeout);
handleRecordedFileHold();
}
// REMOVE ALL RECORDED FILES
this.removeRecordedFiles = function() {
paused = false;
currentPosition.index = currentPosition.shift = 0;
clearTimeout(currentPosition.timeout);
handleRecordedFileHold();
recordedAudioFiles = [];
}
};
var handler = new myRecordHandler();
// you can use this handler in your functions like this:
function recordAudio() {
// records one track and stops former track if there is one
handler.startAudioRecording();
}
function playAudio() {
handler.playRecordedFiles();
}
function pauseAudio() {
handler.pauseRecoredFiles();
}
function resumeAudio() {
pauseAudio();
recordAudio();
}
function stopAudio() {
handler.stopRecordedFiles();
}
Although I could not test your directory/filenames, because I do not have this directory created on my phone, these methods might help you to to store your files in a specific directory as well as with certain filenames:
handler.setDirectory('__YOUR_DIR__');
handler.setFilename('__YOUR_FILENAME__');
handler.setFileType('__YOUR_FILETYPE__');

GetElementsbyClassName requires more?

so im using one of the javascript bgm player solution that works perfectly in a small website that i created.
basically what i want is duplicating the music controller so that there are two music controls i can place on my website.
the script uses javascript's 'GetElementbyID' attribute in order to identify the div, but In order to get the result i want, i would have to make a slight change to 'GetElementsByClassName' so that there are multiple divs.
but for some reason, it didn't work out as i expected, so i did some stackoverflowing and found out the attribute returning some extra array or something like that,
again, im only a starter ar both javascript and jquery,
and i do not know what i need to add or modify in order to make it work.
can anyone help me out? or is there simpler way to make this work using jquery?
see the script below.
and the live site with the BGM player is here : http://xefrontier.com/
if(!window.AudioContext) {
if(!window.webkitAudioContext) {
alert('no audiocontext found');
}
window.AudioContext = window.webkitAudioContext;
}
var context;
var audioBuffer;
var sourceNode;
var analyser;
var javascriptNode;
var ctx = jQuery("#canvas").get()[0].getContext("2d");
var gradient = ctx.createLinearGradient(0, 0, 0, 400);
gradient.addColorStop(0, '#FFFFFF');
gradient.addColorStop(0.50, '#00D4CD');
gradient.addColorStop(0.65, '#FF00CC');
gradient.addColorStop(1, '#1A1A1A');
var currentlyPlaying = 0;
var playing = false;
var trackList = [{
title: "Back For You",
artist: "One Direction",
filename: "bg2.mp3"
}, {
title: "Does He Know",
artist: "One Direction",
filename: "bg3.mp3"
}];
var playbackButton = document.getElementBy("playback-button");
playbackButton.onclick = togglePlayState;
var playIconClass = "fontawesome-play";
var pauseIconClass = "fontawesome-pause";
var nextButton = document.getElementById("next-button");
nextButton.onclick = nextTrack;
var prevButton = document.getElementById("prev-button");
prevButton.onclick = prevTrack;
var playbackIcon = document.getElementById("playback-icon");
function togglePlayState() {
if(!playing) {
startPlayback(currentlyPlaying);
return;
}
switch(context.state) {
case 'running':
playbackIcon.className = playIconClass;
context.suspend();
break;
case 'suspended':
playbackIcon.className = pauseIconClass;
context.resume();
break;
}
}
function displayPlaying() {
var trackInfoElement = document.getElementById("trackInfo");
trackInfoElement.innerHTML = trackList[currentlyPlaying]['title'] + " - " + trackList[currentlyPlaying]['artist'];
}
function displayPlaylist() {
var playlist = document.getElementById('playlist');
playlist.innerHTML = "";
for(var i = currentlyPlaying; i < trackList.length; i++) {
var track = document.createElement('li');
if(i === currentlyPlaying) track.class = "playing";
track.innerHTML = trackList[i]['title'] + ' - ' + trackList[i]['artist'];
playlist.appendChild(track);
}
}
function startPlayback(trackID) {
displayPlaylist()
if(playing) {
stopPlayback();
}
context = new AudioContext()
setupAudioNodes();
loadSound("/xe/" + trackList[trackID]['filename']);
playing = true;
playbackIcon.className = pauseIconClass;
}
function stopPlayback() {
context.close();
playing = false;
playbackIcon.className = playIconClass;
}
function nextTrack() {
if(currentlyPlaying === trackList.length - 1) currentlyPlaying = 0;
else currentlyPlaying += 1;
startPlayback(currentlyPlaying);
}
function prevTrack() {
if(currentlyPlaying === 0) currentlyPlaying = trackList.length - 1;
else currentlyPlaying -= 1;
startPlayback(currentlyPlaying);
}
function setupAudioNodes() {
javascriptNode = context.createScriptProcessor(2048, 1, 1);
javascriptNode.connect(context.destination);
javascriptNode.onaudioprocess = function() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
ctx.clearRect(0, 0, 2000, 1000);
ctx.fillStyle = gradient;
drawSpectrum(array);
}
analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 512;
sourceNode = context.createBufferSource();
sourceNode.onended = function() {
nextTrack();
}
sourceNode.connect(analyser);
analyser.connect(javascriptNode);
sourceNode.connect(context.destination);
}
function loadSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
playSound(buffer);
}, onError);
}
request.send();
}
function playSound(buffer) {
sourceNode.buffer = buffer;
sourceNode.start(0);
}
function onError(e) {
console.log(e);
}
function drawSpectrum(array) {
for(var i = 0; i < (array.length); i++) {
var value = array[i];
ctx.fillRect(i * 8, 350 - value, 2, 50);
}
};

$ outside of jQuery

This app https://developer.mozilla.org/en-US/demos/detail/meet-me-there/launch accepts uploaded photos, attaches a qr code to them, and then allows you to share them. I've attached below the JavaScript for everything except the QR functionality. The app doesn't use jQuery, but at the beginning it assigns a function to the $.
window.onload = function(){
var $ = function(id){
console.log(id);
return document.getElementById(id);
},
When I run the app with the console.log in the above position, it shows that quite a few 'ids' are getting passed through that console.log(id). As the file loads, it logs 'surface', 'cam' and 'upload' and, as you engage the app, it logs 'result', 'sharer', 'uploadedURL' and many others. Problem is that I don't see how everything keeps getting passed through that function for the console.log to log the different 'id's at that point in the code. Therefore, I wonder what the significance of '$' is in this context (no jQuery). Specifically, by creating that '$' function, is it called anytime that any of the other events with $ are run, such as $('upload').onclick = function(){...
Is it working similar to how adding a prototype is working in jquery by using $.prototype.function() in jquery. If so, where does it get this functionality from if there's no jQuery.
window.onload = function(){
var $ = function(id){
console.log(id);
return document.getElementById(id);
},
canvas = $('surface'),
ctx = canvas.getContext('2d'),
watcher, loc='No location provided', located;
$('cam').onchange = function(event){
console.log(event);
console.trace();
var files = event.target.files,
file;
if (files && files.length > 0) {
file = files[0];
try {
var URL = window.URL || window.webkitURL || window.mozURL;
var imgURL = URL.createObjectURL(file);
var img = new Image();
img.id = "tester";
//Load it onto the canvas
img.onload = function() {
console.trace();
canvas.width = this.width;
canvas.height = this.height;
$('info').innerHTML = ("Width: " + this.width + "px, Height: " + this.height + "px");
$('result').width = 400;
$('result').height = (400 / (this.width/this.height)) >> 0;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var codeSize = (canvas.height/4) >> 0;
var imgn = new Image();
imgn.onload = function(){
ctx.drawImage(imgn, (canvas.width-5- codeSize), (canvas.height-5-codeSize), codeSize, codeSize);
$('result').src = canvas.toDataURL();
}
imgn.src = (QR.encode(loc, codeSize, 5));
}
img.src = imgURL;
} catch (e) {
console.log("error: " + e);
}
}
},
// borrowed this functionality from cgack's demo
// https://developer.mozilla.org/en-US/demos/detail/snap-and-share
$('upload').onclick = function(){
$('infomsg').style.display = 'block';
var url = "http://api.imgur.com/2/upload.json",
params = new FormData(),
http = new XMLHttpRequest();
params.append('key','29a8b1db1d8fda0df87006def2307242');
params.append('image',canvas.toDataURL().split(',')[1]);
http.open("POST", url);
http.onload = function() {
var url = JSON.parse(http.responseText).upload.links.imgur_page;
$('uploadedUrl').href = url;
$('uploadedUrl').innerHTML = url;
$('shareFb').href = ("http://www.facebook.com/sharer.php?u="+url);
$('shareTwitter').href = ("http://twitter.com/intent/tweet?url="+url);
$('sharer').style.display = 'block';
$('infomsg').style.display = 'none';
};
http.send(params);
console.log(params);
};
watcher = navigator.geolocation.watchPosition(function(position){
console.trace();
console.log("navigator");
loc = "geo:" + position.coords.latitude + "," +position.coords.longitude;
located = true;
}, function(error){
if(error.code == error.PERMISSION_DENIED || error.code == error.POSITION_UNAVAILABLE)
alert('damn, we were not able to locate you. sorry.');
}
);
};
$ is just a variable name, like any other. It has no special meaning.
"Problem is that I don't see how everything keeps getting passed through that function for the console.log to log the 'id' at that point in the code."
Any time you see $, it's a reference to the function. So a () after it invokes it with the given argument. It's just like any other function, just with a funny name referencing it.
"Therefore, I wonder what the significance of '$' is in this context (no jQuery). Specifically, by creating that '$' function, is it called anytime that any of the other events with $ are run"
Again, no real significance. It's just a function name. If you renamed all the instances of $ to byId, it would behave the same.
window.onload = function(){
// var $ = function(id){
var byId = function(id){
console.log(id);
return document.getElementById(id);
},
canvas = foo('surface'),
ctx = canvas.getContext('2d'),
watcher, loc='No location provided', located;
byId('cam').onchange = function(event){
/* a bunch of code */
},
byId('upload').onclick = function(){
/* a bunch of code */
};
// rest of the code
};

Categories

Resources