The script file and the jsfile reside together on an Apache homepage server.
In the head section of index.html we have
<script type="text/javascript" src="someurl/jsfile.js"></script/>
And in the scriptfile we refer to jsfile by
function init_disp() {array_len = jsfile.length...
Running the scriptfile with or without someurl produces an "'jsfile' is undefined" error. Is there a problem here, or if the server software is blocking the script, does it do it by nulling the variables?
Using IE11 with enhance protect and 64 bit enhance protect, 64 bit Java.
Edit: The entire scriptfile (not my own) is this:
addEvent(window,"load",init_disp);
addEvent(document,"click",show_init);
// function to add an event listener
function addEvent(o,e,f) {
if (o.addEventListener) {
o.addEventListener(e,f,false);
return true;
}
else if (o.attachEvent) {
return o.attachEvent("on"+e,f);
}
else {
return false;
}
}
// integer "random()"
function rand (n)
{
return (Math.floor( Math.random ()*n));
}
// BEGIN customization settings
var char_pause = 60; // pause on each character, milliseconds
var quote_pause = 8000; // pause to show complete quote, milliseconds
// END customization settings
var quoteindex;
var quote,attribution;
var pos;
var box;
var array_len;
var quote_len,attrib_len;
var interval = null;
var busy;
var cursor_span = "<span class=\"quotefont quotecursor\">";
var hide_span = "<span class=\"quotefont hidecolor\">"
var attr_div = "<p></p><div class=\"quotefont attrib\">";
function init_disp() {
array_len = jsfile.length;
box = document.getElementById("quotebox");
quoteindex = rand(array_len);
show_init();
}
function show_init() {
busy = false;
clearInterval(interval);
quote_array = jsfile[quoteindex].split("\t");
quote = quote_array[0];
attribution = quote_array[1];
quote_len = quote.length;
attrib_len = attribution.length;
quoteindex = (quoteindex+1) % array_len;
pos = 0;
interval = setInterval('show_quote()',char_pause);
}
function show_quote() {
pos++;
if(!busy) {
busy = true;
if(pos <= quote_len) {
box.innerHTML = quote.substring(0,pos) +
cursor_span +
quote.substring(pos,pos+1) +
"</span>" +
hide_span +
quote.substring(pos+1) +
"</span>";
}
busy = false;
}
if(pos > quote_len) {
pos = 0;
clearInterval(interval);
interval = setInterval('show_attr()',char_pause);
}
}
function show_attr() {
pos++;
if(!busy) {
busy = true;
if(pos <= attrib_len) {
var attr = attribution.substring(0,pos);
box.innerHTML = quote + attr_div + attr + "</div>";
}
busy = false;
}
if(pos > attrib_len) {
clearInterval(interval);
interval = setInterval('show_init()',quote_pause);
}
}
When you load a Javascript file using <script> tag, that file gets executed, not loaded as a Javascript object.
Related
I built an interface that calls a web API in asp.net (i use c# and javascript/ajax to implement that).
The client side call to the controller, the controller needs to create animation gif and send it back to the client side by a string of base64 or byte array, when the client side gets the base64 he should display it into a canvas.
Now the problem is that the canvas display only the first frame of the animation gif like a static image.
I already read a lot on the internet and find this:
How Do I Convert A GIF Animation To Base64 String And Back To A GIF Animation?
But it's not helped me because I don't want to save the image on the disc just to display it on the client side.
*Note that when I save the image from server side on my disc its save it as gif and display all frames together like I wish, something wrong when I transfer it to client side.
*I use ImageMagick to create the animated gif.
Here is my client side code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link href="Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body style="padding-top: 20px;">
<div class="col-md-10 col-md-offset-1">
<div class="well">
<!---->
<canvas id="canvasImage" width="564" height="120">
<p>We apologize, your browser does not support canvas at this time!</p>
</canvas>
<!---->
</div>
</div>
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: '/api/EngineProccess',
method: 'GET',
success: function (data) {
var imageObj = new Image();
var canvas = document.getElementById("canvasImage");
var context = canvas.getContext('2d');
var image = new Image();
image.onload = function () {
context.drawImage(image, 0, 0);
};
console.log(data);
image.src = "data:image/gif;base64," + data;
},
error: function (jqXHR) {
$('#divErrorText').text(jqXHR.responseText);
$('#divError').show('fade');
}
});
});
</script>
</body>
</html>
and here is the server code:
public class EngineProccessController : ApiController
{
// GET api/EngineProccess
public String Get()
{
using (MagickImageCollection collection = new MagickImageCollection())
{
// Add first image and set the animation delay to 100ms
collection.Add("Snakeware1.gif");
collection[0].AnimationDelay = 100;
// Add second image, set the animation delay to 100ms and flip the image
collection.Add("Snakeware2.gif");
collection[1].AnimationDelay = 100;
collection[1].Flip();
// Optionally reduce colors
QuantizeSettings settings = new QuantizeSettings();
settings.Colors = 256;
collection.Quantize(settings);
// Optionally optimize the images (images should have the same size).
collection.Optimize();
// Save gif
//collection.Write("D://Test01//Test01//Animated.gif");
string data = collection.ToBase64();
return data;
}
}
}
Any ideas?
Please help.
Edit: after some days i found the problem, i use magicimage (magic.net) to create the gif animaited, the base64 was ok but the problem was in the canvas element, the canvas didnt display the animation likei want so i changed the element canvas to be an regular image element () and the changed the src of the image dynamic.
Regards,
Jr.Rafa
Example loading playing gif on canvas.
Sorry but just under 30K answer limit, code and comment very cut down to fit. Ask in comments if needed. See bottom of snippet on basic usage.
/*
The code was created as to the specifications set out in https://www.w3.org/Graphics/GIF/spec-gif89a.txt
The document states usage conditions
"The Graphics Interchange Format(c) is the Copyright property of
CompuServe Incorporated. GIF(sm) is a Service Mark property of
CompuServe Incorporated."
https://en.wikipedia.org/wiki/GIF#Unisys_and_LZW_patent_enforcement last paragraph
Additional sources
https://en.wikipedia.org/wiki/GIF
https://www.w3.org/Graphics/GIF/spec-gif87.txt
*/
var GIF = function () {
var timerID;
var st;
var interlaceOffsets = [0, 4, 2, 1]; // used in de-interlacing.
var interlaceSteps = [8, 8, 4, 2];
var interlacedBufSize = undefined;
var deinterlaceBuf = undefined;
var pixelBufSize = undefined;
var pixelBuf = undefined;
const GIF_FILE = {
GCExt : 0xF9,
COMMENT : 0xFE,
APPExt : 0xFF,
UNKNOWN : 0x01,
IMAGE : 0x2C,
EOF : 59,
EXT : 0x21,
};
var Stream = function (data) { // simple buffered stream
this.data = new Uint8ClampedArray(data);
this.pos = 0;
var len = this.data.length;
this.getString = function (count) {
var s = "";
while (count--) {
s += String.fromCharCode(this.data[this.pos++]);
}
return s;
};
this.readSubBlocks = function () {
var size, count, data;
data = "";
do {
count = size = this.data[this.pos++];
while (count--) {
data += String.fromCharCode(this.data[this.pos++]);
}
} while (size !== 0 && this.pos < len);
return data;
}
this.readSubBlocksB = function () { // reads a set of blocks as binary
var size, count, data;
data = [];
do {
count = size = this.data[this.pos++];
while (count--) {
data.push(this.data[this.pos++]);
}
} while (size !== 0 && this.pos < len);
return data;
}
};
// LZW decoder uncompressed each frame's pixels
var lzwDecode = function (minSize, data) {
var i, pixelPos, pos, clear, eod, size, done, dic, code, last, d, len;
pos = 0;
pixelPos = 0;
dic = [];
clear = 1 << minSize;
eod = clear + 1;
size = minSize + 1;
done = false;
while (!done) {
last = code;
code = 0;
for (i = 0; i < size; i++) {
if (data[pos >> 3] & (1 << (pos & 7))) {
code |= 1 << i;
}
pos++;
}
if (code === clear) { // clear and reset the dictionary
dic = [];
size = minSize + 1;
for (i = 0; i < clear; i++) {
dic[i] = [i];
}
dic[clear] = [];
dic[eod] = null;
continue;
}
if (code === eod) { // end of data
done = true;
return;
}
if (code >= dic.length) {
dic.push(dic[last].concat(dic[last][0]));
} else
if (last !== clear) {
dic.push(dic[last].concat(dic[code][0]));
}
d = dic[code];
len = d.length;
for (i = 0; i < len; i++) {
pixelBuf[pixelPos++] = d[i];
}
if (dic.length === (1 << size) && size < 12) {
size++;
}
}
};
var parseColourTable = function (count) { // get a colour table of length count
// Each entry is 3 bytes, for RGB.
var colours = [];
for (var i = 0; i < count; i++) {
colours.push([st.data[st.pos++], st.data[st.pos++], st.data[st.pos++]]);
}
return colours;
};
var parse = function () { // read the header. This is the starting point of the decode and async calls parseBlock
var bitField;
st.pos += 6; // skip the first stuff see GifEncoder for details
gif.width = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
gif.height = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
bitField = st.data[st.pos++];
gif.colorRes = (bitField & 0b1110000) >> 4;
gif.globalColourCount = 1 << ((bitField & 0b111) + 1);
gif.bgColourIndex = st.data[st.pos++];
st.pos++; // ignoring pixel aspect ratio. if not 0, aspectRatio = (pixelAspectRatio + 15) / 64
if (bitField & 0b10000000) { // global colour flag
gif.globalColourTable = parseColourTable(gif.globalColourCount);
}
setTimeout(parseBlock, 0);
};
var parseAppExt = function () { // get application specific data. Netscape added iterations and terminator. Ignoring that
st.pos += 1;
if ('NETSCAPE' === st.getString(8)) {
st.pos += 8; // ignoring this data. iterations (word) and terminator (byte)
} else {
st.pos += 3; // 3 bytes of string usually "2.0" when identifier is NETSCAPE
st.readSubBlocks(); // unknown app extension
}
};
var parseGCExt = function () { // get GC data
var bitField;
st.pos++;
bitField = st.data[st.pos++];
gif.disposalMethod = (bitField & 0b11100) >> 2;
gif.transparencyGiven = bitField & 0b1 ? true : false; // ignoring bit two that is marked as userInput???
gif.delayTime = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
gif.transparencyIndex = st.data[st.pos++];
st.pos++;
};
var parseImg = function () { // decodes image data to create the indexed pixel image
var deinterlace, frame, bitField;
deinterlace = function (width) { // de interlace pixel data if needed
var lines, fromLine, pass, toline;
lines = pixelBufSize / width;
fromLine = 0;
if (interlacedBufSize !== pixelBufSize) {
deinterlaceBuf = new Uint8Array(pixelBufSize);
interlacedBufSize = pixelBufSize;
}
for (pass = 0; pass < 4; pass++) {
for (toLine = interlaceOffsets[pass]; toLine < lines; toLine += interlaceSteps[pass]) {
deinterlaceBuf.set(pixelBuf.subArray(fromLine, fromLine + width), toLine * width);
fromLine += width;
}
}
};
frame = {}
gif.frames.push(frame);
frame.disposalMethod = gif.disposalMethod;
frame.time = gif.length;
frame.delay = gif.delayTime * 10;
gif.length += frame.delay;
if (gif.transparencyGiven) {
frame.transparencyIndex = gif.transparencyIndex;
} else {
frame.transparencyIndex = undefined;
}
frame.leftPos = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
frame.topPos = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
frame.width = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
frame.height = (st.data[st.pos++]) + ((st.data[st.pos++]) << 8);
bitField = st.data[st.pos++];
frame.localColourTableFlag = bitField & 0b10000000 ? true : false;
if (frame.localColourTableFlag) {
frame.localColourTable = parseColourTable(1 << ((bitField & 0b111) + 1));
}
if (pixelBufSize !== frame.width * frame.height) { // create a pixel buffer if not yet created or if current frame size is different from previous
pixelBuf = new Uint8Array(frame.width * frame.height);
pixelBufSize = frame.width * frame.height;
}
lzwDecode(st.data[st.pos++], st.readSubBlocksB()); // decode the pixels
if (bitField & 0b1000000) { // de interlace if needed
frame.interlaced = true;
deinterlace(frame.width);
} else {
frame.interlaced = false;
}
processFrame(frame); // convert to canvas image
};
var processFrame = function (frame) {
var ct, cData, dat, pixCount, ind, useT, i, pixel, pDat, col, frame, ti;
frame.image = document.createElement('canvas');
frame.image.width = gif.width;
frame.image.height = gif.height;
frame.image.ctx = frame.image.getContext("2d");
ct = frame.localColourTableFlag ? frame.localColourTable : gif.globalColourTable;
if (gif.lastFrame === null) {
gif.lastFrame = frame;
}
useT = (gif.lastFrame.disposalMethod === 2 || gif.lastFrame.disposalMethod === 3) ? true : false;
if (!useT) {
frame.image.ctx.drawImage(gif.lastFrame.image, 0, 0, gif.width, gif.height);
}
cData = frame.image.ctx.getImageData(frame.leftPos, frame.topPos, frame.width, frame.height);
ti = frame.transparencyIndex;
dat = cData.data;
if (frame.interlaced) {
pDat = deinterlaceBuf;
} else {
pDat = pixelBuf;
}
pixCount = pDat.length;
ind = 0;
for (i = 0; i < pixCount; i++) {
pixel = pDat[i];
col = ct[pixel];
if (ti !== pixel) {
dat[ind++] = col[0];
dat[ind++] = col[1];
dat[ind++] = col[2];
dat[ind++] = 255; // Opaque.
} else
if (useT) {
dat[ind + 3] = 0; // Transparent.
ind += 4;
} else {
ind += 4;
}
}
frame.image.ctx.putImageData(cData, frame.leftPos, frame.topPos);
gif.lastFrame = frame;
if (!gif.waitTillDone && typeof gif.onload === "function") { // if !waitTillDone the call onload now after first frame is loaded
doOnloadEvent();
}
};
var finnished = function () { // called when the load has completed
gif.loading = false;
gif.frameCount = gif.frames.length;
gif.lastFrame = null;
st = undefined;
gif.complete = true;
gif.disposalMethod = undefined;
gif.transparencyGiven = undefined;
gif.delayTime = undefined;
gif.transparencyIndex = undefined;
gif.waitTillDone = undefined;
pixelBuf = undefined; // dereference pixel buffer
deinterlaceBuf = undefined; // dereference interlace buff (may or may not be used);
pixelBufSize = undefined;
deinterlaceBuf = undefined;
gif.currentFrame = 0;
if (gif.frames.length > 0) {
gif.image = gif.frames[0].image;
}
doOnloadEvent();
if (typeof gif.onloadall === "function") {
(gif.onloadall.bind(gif))({
type : 'loadall',
path : [gif]
});
}
if (gif.playOnLoad) {
gif.play();
}
}
var canceled = function () { // called if the load has been cancelled
finnished();
if (typeof gif.cancelCallback === "function") {
(gif.cancelCallback.bind(gif))({
type : 'canceled',
path : [gif]
});
}
}
var parseExt = function () { // parse extended blocks
switch (st.data[st.pos++]) {
case GIF_FILE.GCExt:
parseGCExt();
break;
case GIF_FILE.COMMENT:
gif.comment += st.readSubBlocks(); // found a comment field
break;
case GIF_FILE.APPExt:
parseAppExt();
break;
case GIF_FILE.UNKNOWN: // not keeping this data
st.pos += 13; // deliberate fall through to default
default: // not keeping this if it happens
st.readSubBlocks();
break;
}
}
var parseBlock = function () { // parsing the blocks
if (gif.cancel !== undefined && gif.cancel === true) {
canceled();
return;
}
switch (st.data[st.pos++]) {
case GIF_FILE.IMAGE: // image block
parseImg();
if (gif.firstFrameOnly) {
finnished();
return;
}
break;
case GIF_FILE.EOF: // EOF found so cleanup and exit.
finnished();
return;
case GIF_FILE.EXT: // extend block
default:
parseExt();
break;
}
if (typeof gif.onprogress === "function") {
gif.onprogress({
bytesRead : st.pos,
totalBytes : st.data.length,
frame : gif.frames.length
});
}
setTimeout(parseBlock, 0);
};
var cancelLoad = function (callback) {
if (gif.complete) {
return false;
}
gif.cancelCallback = callback;
gif.cancel = true;
return true;
}
var error = function (type) {
if (typeof gif.onerror === "function") {
(gif.onerror.bind(this))({
type : type,
path : [this]
});
}
gif.onerror = undefined;
gif.onload = undefined;
gif.loading = false;
}
var doOnloadEvent = function () { // fire onload event if set
gif.currentFrame = 0;
gif.lastFrameAt = new Date().valueOf();
gif.nextFrameAt = new Date().valueOf();
if (typeof gif.onload === "function") {
(gif.onload.bind(gif))({
type : 'load',
path : [gif]
});
}
gif.onload = undefined;
gif.onerror = undefined;
}
var dataLoaded = function (data) {
st = new Stream(data);
parse();
}
var loadGif = function (filename) { // starts the load
var ajax = new XMLHttpRequest();
ajax.responseType = "arraybuffer";
ajax.onload = function (e) {
if (e.target.status === 400) {
error("Bad Request response code");
} else if (e.target.status === 404) {
error("File not found");
} else {
dataLoaded(ajax.response);
}
};
ajax.open('GET', filename, true);
ajax.send();
ajax.onerror = function (e) {
error("File error");
};
this.src = filename;
this.loading = true;
}
function play() { // starts play if paused
if (!gif.playing) {
gif.paused = false;
gif.playing = true;
playing();
}
}
function pause() { // stops play
gif.paused = true;
gif.playing = false;
clearTimeout(timerID);
}
function togglePlay(){
if(gif.paused || !gif.playing){
gif.play();
}else{
gif.pause();
}
}
function seekFrame(frame) { // seeks to frame number.
clearTimeout(timerID);
frame = frame < 0 ? (frame % gif.frames.length) + gif.frames.length : frame;
gif.currentFrame = frame % gif.frames.length;
if (gif.playing) {
playing();
} else {
gif.image = gif.frames[gif.currentFrame].image;
}
}
function seek(time) { // time in Seconds
clearTimeout(timerID);
if (time < 0) {
time = 0;
}
time *= 1000; // in ms
time %= gif.length;
var frame = 0;
while (time > gif.frames[frame].time + gif.frames[frame].delay && frame < gif.frames.length) {
frame += 1;
}
gif.currentFrame = frame;
if (gif.playing) {
playing();
} else {
gif.image = gif.frames[gif.currentFrame].image;
}
}
function playing() {
var delay;
var frame;
if (gif.playSpeed === 0) {
gif.pause();
return;
}
if (gif.playSpeed < 0) {
gif.currentFrame -= 1;
if (gif.currentFrame < 0) {
gif.currentFrame = gif.frames.length - 1;
}
frame = gif.currentFrame;
frame -= 1;
if (frame < 0) {
frame = gif.frames.length - 1;
}
delay = -gif.frames[frame].delay * 1 / gif.playSpeed;
} else {
gif.currentFrame += 1;
gif.currentFrame %= gif.frames.length;
delay = gif.frames[gif.currentFrame].delay * 1 / gif.playSpeed;
}
gif.image = gif.frames[gif.currentFrame].image;
timerID = setTimeout(playing, delay);
}
var gif = { // the gif image object
onload : null, // fire on load. Use waitTillDone = true to have load fire at end or false to fire on first frame
onerror : null, // fires on error
onprogress : null, // fires a load progress event
onloadall : null, // event fires when all frames have loaded and gif is ready
paused : false, // true if paused
playing : false, // true if playing
waitTillDone : true, // If true onload will fire when all frames loaded, if false, onload will fire when first frame has loaded
loading : false, // true if still loading
firstFrameOnly : false, // if true only load the first frame
width : null, // width in pixels
height : null, // height in pixels
frames : [], // array of frames
comment : "", // comments if found in file. Note I remember that some gifs have comments per frame if so this will be all comment concatenated
length : 0, // gif length in ms (1/1000 second)
currentFrame : 0, // current frame.
frameCount : 0, // number of frames
playSpeed : 1, // play speed 1 normal, 2 twice 0.5 half, -1 reverse etc...
lastFrame : null, // temp hold last frame loaded so you can display the gif as it loads
image : null, // the current image at the currentFrame
playOnLoad : true, // if true starts playback when loaded
// functions
load : loadGif, // call this to load a file
cancel : cancelLoad, // call to stop loading
play : play, // call to start play
pause : pause, // call to pause
seek : seek, // call to seek to time
seekFrame : seekFrame, // call to seek to frame
togglePlay : togglePlay, // call to toggle play and pause state
};
return gif;
}
/*=================================================================
USEAGE Example below
Image used from Wiki see HTML for requiered image atribution
===================================================================*/
const ctx = canvas.getContext("2d");
ctx.font = "16px arial";
var changeFrame = false;
var changeSpeed = false;
frameNum.addEventListener("mousedown",()=>{changeFrame = true ; changeSpeed = false});
speedInput.addEventListener("mousedown",()=>{changeSpeed = true; changeFrame = false});
const gifSrc = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Odessa_TX_Oil_Well_with_Lufkin_320D_pumping_unit.gif/220px-Odessa_TX_Oil_Well_with_Lufkin_320D_pumping_unit.gif"
var myGif = GIF(); // Creates a new gif
myGif.load(gifSrc); // set URL and load
myGif.onload = function(event){ // fires when loading is complete
frameNum.max = myGif.frameCount-1;
animate();
}
myGif.onprogress = function(event){ // Note this function is not bound to myGif
if(canvas.width !== myGif.width || canvas.height !== myGif.height){
canvas.width = myGif.width;
canvas.height = myGif.height;
ctx.font = "16px arial";
}
if(myGif.lastFrame !== null){
ctx.drawImage(myGif.lastFrame.image,0,0);
}
ctx.fillStyle = "black";
ctx.fillText("Loaded frame "+event.frame,8,20);
frameNum.max = event.frame-1;
frameNum.value = event.frame;
frameText.textContent = frameNum.value + "/" + (frameNum.max-1);
}
myGif.onerror = function(event){
ctx.fillStyle = "black";
ctx.fillText("Could not load the Gif ",8,20);
ctx.fillText("Error : " + event.type,8,40);
}
function animate(){
if(changeFrame){
if(myGif.playing){
myGif.pause();
}
myGif.seekFrame(Number(frameNum.value));
}else if(changeSpeed){
myGif.playSpeed = speedInput.value;
if(myGif.paused){
myGif.play();
}
}
frameNum.value = myGif.currentFrame;
frameText.textContent = frameNum.value + "/" + frameNum.max;
if(myGif.paused){
speedInput.value = 0;
}else{
speedInput.value = myGif.playSpeed;
}
speedText.textContent = speedInput.value;
ctx.drawImage(myGif.image,0,0);
requestAnimationFrame(animate);
}
canvas { border : 2px solid black; }
p { font-family : arial; font-size : 12px }
<canvas id="canvas"></canvas>
<div id="inputs">
<input id="frameNum" type = "range" min="0" max="1" step="1" value="0"></input>
Frame : <span id="frameText"></span><br>
<input id="speedInput" type = "range" min="-3" max="3" step="0.1" value="1"></input>
Speed : <span id="speedText"></span><br>
</div>
<p>Image source <br>By DASL51984 - Original YouTube video by user "derekdz", looped by DASL51984, CC BY-SA 4.0, Link</p>
I'm building a DTMF dial emulator. After a certain function runs, the function dial() is executed. Currently, I hear the ringback tone once but I cannot get it to ring twice.
I originally tried to get the same file to play twice by resetting the audio currentTime to 0 and playing it again after a delay of 4 seconds (the duration between ringback tones in North America).
That didn't work so I thought perhaps JS didn't want me playing the same audio twice. So I recreated it again as a second variable and created a new function for that next in the sequence for dial().
That didn't work, but if I added an alert box before ringingTone2 played, it played as soon as I dismissed the alert.
Obviously, I can't have an alert dialog when this is done. How can I have the sound play twice, but with a 4 second gap in between? I've had no success with setTimeout(ring(), 4000) either.
Here is some of the code pertaining to this issue:
var ringingTone1 = new Audio('DTMF-ringbackTone.mp3');
var ringingTone2 = new Audio('DTMF-ringbackTone.mp3');
function dial() {
ring();
function ring() {
ringingTone1.play();
setTimeout(ringingTone2.play(),4000);
}
Right now, JS basically plays the ringback tone once and moves onto to what is after this in the script.
The following causes it to stop working:
function dial() {
ring();
function ring() {
var played = 0;
var maxPlay = 2;
var ringingTone = document.getElementById('music');
var playBtn = document.getElementById('playbtn');
ringingTone.onplay = ring() {
//played counter
played++;
};
ringingTone.addEventListener("ended", ring() {
//reset to start point
ringingTone.currentTime = 0;
if (played < maxPlay) {
ringingTone.play();
} else {
played = 0;
}
});
playBtn.addEventListener("click", ring() {
ringingTone.play();
});
}
This is my complete script:
var availableNumbers = ["0", "911"];
function numberSuggestion() {
var randomNumber = Math.random() * availableNumbers.length -1;
var suggestedNumber = availableNumbers[randomNumber];
document.getElementById("suggestion").innerHTML = "How about dialing " + suggestedNumber + "? Don't like this number? Click the button above again!";
}
var dialTone;
function offHook() {
document.getElementById("WE2500").style.display = "none";
document.getElementById("dialPad").style.display = "block";
dialTone = new Audio('dialTone.m4a');
dialTone.play();
}
var number = "";
var timeout;
function numberDial() {
if (dialTone) {
dialTone.pause();
dialTone.currentTime = 0;
}
clearTimeout(timeout);
timeout = setTimeout(dial, 2000);
}
function dial1() {
numberDial();
number = number + "1";
var tone1 = new Audio('DTMF-1.wav');
tone1.play();
}
function dial2() {
numberDial();
number = number + "2";
var tone2 = new Audio('DTMF-2.wav');
tone2.play();
}
function dial3() {
numberDial();
number = number + "3";
var tone3 = new Audio('DTMF-3.wav');
tone3.play();
}
function dial4() {
numberDial();
number = number + "4";
var tone4 = new Audio('DTMF-5.wav');
tone4.play();
}
function dial5() {
numberDial();
number = number + "5";
var tone5 = new Audio('DTMF-5.wav');
tone5.play();
}
function dial6() {
numberDial();
number = number + "6";
var tone6 = new Audio('DTMF-6.wav');
tone6.play();
}
function dial7() {
numberDial();
number = number + "7";
var tone7 = new Audio('DTMF-7.wav');
tone7.play();
}
function dial8() {
numberDial();
number = number + "8";
var tone8 = new Audio('DTMF-8.wav');
tone8.play();
}
function dial9() {
numberDial();
number = number + "9";
var tone9 = new Audio('DTMF-9.wav');
tone9.play();
}
function dial0() {
numberDial();
number = number + "0";
var tone0 = new Audio('DTMF-0.wav');
tone0.play();
}
function dialStar() {
numberDial();
number = number + "*";
var toneStar = new Audio('DTMF-star.wav');
toneStar.play();
}
function dialPound() {
numberDial();
number = number + "#";
var tonePound = new Audio('DTMF-pound.wav');
tonePound.play();
}
//var ringingTone1 = new Audio('DTMF-ringbackTone.mp3');
//var ringingTone2 = new Audio('DTMF-ringbackTone.mp3');
function dial() {
ring();
function ring() {
var played = 0;
var maxPlay = 2;
var ringingTone = document.getElementById('music');
var playBtn = document.getElementById('playbtn');
ringingTone.onplay = ring() {
//played counter
played++;
};
ringingTone.addEventListener("ended", ring() {
//reset to start point
ringingTone.currentTime = 0;
if (played < maxPlay) {
ringingTone.play();
} else {
played = 0;
}
});
playBtn.addEventListener("click", ring() {
ringingTone.play();
});
}
switch(number) {
case "0":
break;
case "911":
var pickup911 = new Audio('911-xxx-fleet.mp3');
pickup911.play();
break;
default:
}
}
The idea is simple, one counter for played time, one constant for max play.
Use the onplay event to increase the counter everytime a audio played.
Use the ended event to replay the audio if max play time not reached yet. Otherwise, set played count to 0.
var played = 0;
var maxPlay = 2;
var ringingTone = document.getElementById('music');
var playBtn = document.getElementById('playbtn');
ringingTone.onplay = function() {
//played counter
played++;
};
ringingTone.addEventListener("ended", function() {
//reset to start point
ringingTone.currentTime = 0;
if (played < maxPlay) {
ringingTone.play();
} else {
played = 0;
}
});
playBtn.addEventListener("click", function() {
ringingTone.play();
});
<audio id="music" src="http://www.noiseaddicts.com/samples_1w72b820/3732.mp3"></audio>
<button id="playbtn">Play me</button>
Calling a function in setTimeout (and I think it applies to all callbacks) using () will cause the code inside to be evaluated immediately (which in your case meant play both audios at the same time).
Hence my comment above to use .play without (), which looks like doesn't work. However, this does work:
function dial() {
function ring() {
ringingTone.play();
}
ring();
setTimeout(ring, 4000);
}
dial();
http://jsfiddle.net/tL3monyp/
(audio src unscrupulously copied from Daniel's answer ;-)
I've also added 2 timeouts to illustrate calling the function with and without ().
I am trying to implement a fancy slider from codepen in wordpress. I have correctly added the script using the enqueue script method. I know I did it coorectly because it worked for a very small experiment I tried. Now the pen is: http://codepen.io/suez/pen/wMMgXp .
(function() {
var $$ = function(selector, context) {
var context = context || document;
var elements = context.querySelectorAll(selector);
return [].slice.call(elements);
};
function _fncSliderInit($slider, options) {
var prefix = ".fnc-";
var $slider = $slider;
var $slidesCont = $slider.querySelector(prefix + "slider__slides");
var $slides = $$(prefix + "slide", $slider);
var $controls = $$(prefix + "nav__control", $slider);
var $controlsBgs = $$(prefix + "nav__bg", $slider);
var $progressAS = $$(prefix + "nav__control-progress", $slider);
var numOfSlides = $slides.length;
var curSlide = 1;
var sliding = false;
var slidingAT = +parseFloat(getComputedStyle($slidesCont)["transition-duration"]) * 1000;
var slidingDelay = +parseFloat(getComputedStyle($slidesCont)["transition-delay"]) * 1000;
var autoSlidingActive = false;
var autoSlidingTO;
var autoSlidingDelay = 5000; // default autosliding delay value
var autoSlidingBlocked = false;
var $activeSlide;
var $activeControlsBg;
var $prevControl;
function setIDs() {
$slides.forEach(function($slide, index) {
$slide.classList.add("fnc-slide-" + (index + 1));
});
$controls.forEach(function($control, index) {
$control.setAttribute("data-slide", index + 1);
$control.classList.add("fnc-nav__control-" + (index + 1));
});
$controlsBgs.forEach(function($bg, index) {
$bg.classList.add("fnc-nav__bg-" + (index + 1));
});
};
setIDs();
function afterSlidingHandler() {
$slider.querySelector(".m--previous-slide").classList.remove("m--active-slide", "m--previous-slide");
$slider.querySelector(".m--previous-nav-bg").classList.remove("m--active-nav-bg", "m--previous-nav-bg");
$activeSlide.classList.remove("m--before-sliding");
$activeControlsBg.classList.remove("m--nav-bg-before");
$prevControl.classList.remove("m--prev-control");
$prevControl.classList.add("m--reset-progress");
var triggerLayout = $prevControl.offsetTop;
$prevControl.classList.remove("m--reset-progress");
sliding = false;
var layoutTrigger = $slider.offsetTop;
if (autoSlidingActive && !autoSlidingBlocked) {
setAutoslidingTO();
}
};
function performSliding(slideID) {
if (sliding) return;
sliding = true;
window.clearTimeout(autoSlidingTO);
curSlide = slideID;
$prevControl = $slider.querySelector(".m--active-control");
$prevControl.classList.remove("m--active-control");
$prevControl.classList.add("m--prev-control");
$slider.querySelector(prefix + "nav__control-" + slideID).classList.add("m--active-control");
$activeSlide = $slider.querySelector(prefix + "slide-" + slideID);
$activeControlsBg = $slider.querySelector(prefix + "nav__bg-" + slideID);
$slider.querySelector(".m--active-slide").classList.add("m--previous-slide");
$slider.querySelector(".m--active-nav-bg").classList.add("m--previous-nav-bg");
$activeSlide.classList.add("m--before-sliding");
$activeControlsBg.classList.add("m--nav-bg-before");
var layoutTrigger = $activeSlide.offsetTop;
$activeSlide.classList.add("m--active-slide");
$activeControlsBg.classList.add("m--active-nav-bg");
setTimeout(afterSlidingHandler, slidingAT + slidingDelay);
};
function controlClickHandler() {
if (sliding) return;
if (this.classList.contains("m--active-control")) return;
if (options.blockASafterClick) {
autoSlidingBlocked = true;
$slider.classList.add("m--autosliding-blocked");
}
var slideID = +this.getAttribute("data-slide");
performSliding(slideID);
};
$controls.forEach(function($control) {
$control.addEventListener("click", controlClickHandler);
});
function setAutoslidingTO() {
window.clearTimeout(autoSlidingTO);
var delay = +options.autoSlidingDelay || autoSlidingDelay;
curSlide++;
if (curSlide > numOfSlides) curSlide = 1;
autoSlidingTO = setTimeout(function() {
performSliding(curSlide);
}, delay);
};
if (options.autoSliding || +options.autoSlidingDelay > 0) {
if (options.autoSliding === false) return;
autoSlidingActive = true;
setAutoslidingTO();
$slider.classList.add("m--with-autosliding");
var triggerLayout = $slider.offsetTop;
var delay = +options.autoSlidingDelay || autoSlidingDelay;
delay += slidingDelay + slidingAT;
$progressAS.forEach(function($progress) {
$progress.style.transition = "transform " + (delay / 1000) + "s";
});
}
$slider.querySelector(".fnc-nav__control:first-child").classList.add("m--active-control");
};
var fncSlider = function(sliderSelector, options) {
var $sliders = $$(sliderSelector);
$sliders.forEach(function($slider) {
_fncSliderInit($slider, options);
});
};
window.fncSlider = fncSlider;
}());
/* not part of the slider scripts */
/* Slider initialization
options:
autoSliding - boolean
autoSlidingDelay - delay in ms. If audoSliding is on and no value provided, default value is 5000
blockASafterClick - boolean. If user clicked any sliding control, autosliding won't start again
*/
fncSlider(".example-slider", {autoSlidingDelay: 4000});
var $demoCont = document.querySelector(".demo-cont");
[].slice.call(document.querySelectorAll(".fnc-slide__action-btn")).forEach(function($btn) {
$btn.addEventListener("click", function() {
$demoCont.classList.toggle("credits-active");
});
});
document.querySelector(".demo-cont__credits-close").addEventListener("click", function() {
$demoCont.classList.remove("credits-active");
});
document.querySelector(".js-activate-global-blending").addEventListener("click", function() {
document.querySelector(".example-slider").classList.toggle("m--global-blending-active");
});
The javascript code can e found above and in the mentioned link.I know that in wordpress we have to use jQuery in place of $ but I still can't seem to figure out how to do it in this case. And one more thing, the css is in scass form but I have taken the compiled css form but I don't think that is causing any problem (rignt?) Everything I have tried till this point has failed. Any help will be appreciated
You can use $ instead of jQuery in WordPress so long as you wrap all your code inside the following:
(function($) {
// Your code goes here
})( jQuery );
If the code is in the header (before the document is ready) then instead use:
jQuery(document).ready(function( $ ) {
// Your code goes here
});
If your code is still having problems, then please include both the enqueue code in your theme and the error messages
I have been experimenting with cute file browser (perfect for my project).
Cute File Browser
But came accross a incomaptibiliy issue. Im not getting any errors in console, but im also not getting any elements being rendered. I have switched libraries about and I think this plugin only works with jquery version 1.11.0, the version my project is using is 1.11.3.
How should I attempt to fix/update this small script?
CUTE SCRIPT:
$(function(){
var filemanager = $('.filemanager'),
breadcrumbs = $('.breadcrumbs'),
fileList = filemanager.find('.data');
// Start by fetching the file data from scan.php with an AJAX request
$.get('scan.php', function(data) {
var response = [data],
currentPath = '',
breadcrumbsUrls = [];
var folders = [],
files = [];
// This event listener monitors changes on the URL. We use it to
// capture back/forward navigation in the browser.
$(window).on('hashchange', function(){
goto(window.location.hash);
// We are triggering the event. This will execute
// this function on page load, so that we show the correct folder:
}).trigger('hashchange');
// Hiding and showing the search box
filemanager.find('.search').click(function(){
var search = $(this);
search.find('span').hide();
search.find('input[type=search]').show().focus();
});
// Listening for keyboard input on the search field.
// We are using the "input" event which detects cut and paste
// in addition to keyboard input.
filemanager.find('input').on('input', function(e){
folders = [];
files = [];
var value = this.value.trim();
if(value.length) {
filemanager.addClass('searching');
// Update the hash on every key stroke
window.location.hash = 'search=' + value.trim();
}
else {
filemanager.removeClass('searching');
window.location.hash = encodeURIComponent(currentPath);
}
}).on('keyup', function(e){
// Clicking 'ESC' button triggers focusout and cancels the search
var search = $(this);
if(e.keyCode == 27) {
search.trigger('focusout');
}
}).focusout(function(e){
// Cancel the search
var search = $(this);
if(!search.val().trim().length) {
window.location.hash = encodeURIComponent(currentPath);
search.hide();
search.parent().find('span').show();
}
});
// Clicking on folders
fileList.on('click', 'li.folders', function(e){
e.preventDefault();
var nextDir = $(this).find('a.folders').attr('href');
if(filemanager.hasClass('searching')) {
// Building the breadcrumbs
breadcrumbsUrls = generateBreadcrumbs(nextDir);
filemanager.removeClass('searching');
filemanager.find('input[type=search]').val('').hide();
filemanager.find('span').show();
}
else {
breadcrumbsUrls.push(nextDir);
}
window.location.hash = encodeURIComponent(nextDir);
currentPath = nextDir;
});
// Clicking on breadcrumbs
breadcrumbs.on('click', 'a', function(e){
e.preventDefault();
var index = breadcrumbs.find('a').index($(this)),
nextDir = breadcrumbsUrls[index];
breadcrumbsUrls.length = Number(index);
window.location.hash = encodeURIComponent(nextDir);
});
// Navigates to the given hash (path)
function goto(hash) {
hash = decodeURIComponent(hash).slice(1).split('=');
if (hash.length) {
var rendered = '';
// if hash has search in it
if (hash[0] === 'search') {
filemanager.addClass('searching');
rendered = searchData(response, hash[1].toLowerCase());
if (rendered.length) {
currentPath = hash[0];
render(rendered);
}
else {
render(rendered);
}
}
// if hash is some path
else if (hash[0].trim().length) {
rendered = searchByPath(hash[0]);
if (rendered.length) {
currentPath = hash[0];
breadcrumbsUrls = generateBreadcrumbs(hash[0]);
render(rendered);
}
else {
currentPath = hash[0];
breadcrumbsUrls = generateBreadcrumbs(hash[0]);
render(rendered);
}
}
// if there is no hash
else {
currentPath = data.path;
breadcrumbsUrls.push(data.path);
render(searchByPath(data.path));
}
}
}
// Splits a file path and turns it into clickable breadcrumbs
function generateBreadcrumbs(nextDir){
var path = nextDir.split('/').slice(0);
for(var i=1;i<path.length;i++){
path[i] = path[i-1]+ '/' +path[i];
}
return path;
}
// Locates a file by path
function searchByPath(dir) {
var path = dir.split('/'),
demo = response,
flag = 0;
for(var i=0;i<path.length;i++){
for(var j=0;j<demo.length;j++){
if(demo[j].name === path[i]){
flag = 1;
demo = demo[j].items;
break;
}
}
}
demo = flag ? demo : [];
return demo;
}
// Recursively search through the file tree
function searchData(data, searchTerms) {
data.forEach(function(d){
if(d.type === 'folder') {
searchData(d.items,searchTerms);
if(d.name.toLowerCase().match(searchTerms)) {
folders.push(d);
}
}
else if(d.type === 'file') {
if(d.name.toLowerCase().match(searchTerms)) {
files.push(d);
}
}
});
return {folders: folders, files: files};
}
// Render the HTML for the file manager
function render(data) {
var scannedFolders = [],
scannedFiles = [];
if(Array.isArray(data)) {
data.forEach(function (d) {
if (d.type === 'folder') {
scannedFolders.push(d);
}
else if (d.type === 'file') {
scannedFiles.push(d);
}
});
}
else if(typeof data === 'object') {
scannedFolders = data.folders;
scannedFiles = data.files;
}
// Empty the old result and make the new one
fileList.empty().hide();
if(!scannedFolders.length && !scannedFiles.length) {
filemanager.find('.nothingfound').show();
}
else {
filemanager.find('.nothingfound').hide();
}
if(scannedFolders.length) {
scannedFolders.forEach(function(f) {
var itemsLength = f.items.length,
name = escapeHTML(f.name),
icon = '<span class="icon folder"></span>';
if(itemsLength) {
icon = '<span class="icon folder full"></span>';
}
if(itemsLength == 1) {
itemsLength += ' item';
}
else if(itemsLength > 1) {
itemsLength += ' items';
}
else {
itemsLength = 'Empty';
}
var folder = $('<li class="folders">'+icon+'<span class="name">' + name + '</span> <span class="details">' + itemsLength + '</span></li>');
folder.appendTo(fileList);
});
}
if(scannedFiles.length) {
scannedFiles.forEach(function(f) {
var fileSize = bytesToSize(f.size),
name = escapeHTML(f.name),
fileType = name.split('.'),
icon = '<span class="icon file"></span>';
fileType = fileType[fileType.length-1];
icon = '<span class="icon file f-'+fileType+'">.'+fileType+'</span>';
var file = $('<li class="files">'+icon+'<span class="name">'+ name +'</span> <span class="details">'+fileSize+'</span></li>');
file.appendTo(fileList);
});
}
// Generate the breadcrumbs
var url = '';
if(filemanager.hasClass('searching')){
url = '<span>Search results: </span>';
fileList.removeClass('animated');
}
else {
fileList.addClass('animated');
breadcrumbsUrls.forEach(function (u, i) {
var name = u.split('/');
if (i !== breadcrumbsUrls.length - 1) {
url += '<span class="folderName">' + name[name.length-1] + '</span> <span class="arrow">→</span> ';
}
else {
url += '<span class="folderName">' + name[name.length-1] + '</span>';
}
});
}
breadcrumbs.text('').append(url);
// Show the generated elements
fileList.animate({'display':'inline-block'});
}
// This function escapes special html characters in names
function escapeHTML(text) {
return text.replace(/\&/g,'&').replace(/\</g,'<').replace(/\>/g,'>');
}
// Convert file sizes from bytes to human readable units
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Bytes';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
});
});
I tweaked certain jquery methods around in the render function using the 1.11.3 version and it appears animate() was causing the issues.
Change Script.js line 375:
From fileList.animate({'display':'inline-block'});
To fileList.css('display','inline-block');.
EDIT:
I noticed a slightly more improved method of revealing the hidden filelist without using inline styles and adding it to a more appoporate section of the script. Simply use filelist.show() in the following section of the render function.
change Script.js line 286-291:
if(!scannedFolders.length && !scannedFiles.length) {
filemanager.find('.nothingfound').show();
fileList.hide();
}
else {
filemanager.find('.nothingfound').hide();
fileList.show();
}
Hiding the filelist using filelist.hide() also helped me with a style bug relating to the .nothing-found error message being pushed down to the bottom of the page when needing to use a fixed height on the filelist.
Now im not depenedant on what version of jquery im using. Hope this helps others using this nice little script.
This is a design portfolio page. On load, the JSON data is retrieved via ajax, and one of the keys is used to generate a list of '.project-links' (no project is displayed on load, and the project images are loaded only when a project is selected (see showProj function)). My question regards the fadein/fadeout: the images are still painting onto the screen after the fade in completes, despite the project content being defined/loaded within the fadeOut callback; can someone please enlighten me as to how I can tweak this so that the fadeIn won't run until the projImages are loaded?
Thank you, svs.
function ajaxReq() {
var request = new XMLHttpRequest();
return request;
}
function makeLinks(projects) { // result = getJsonData > request.responseText
var projectList = document.getElementById("project-list");
for (var project in projects) {
if (projects[project].status !== "DNU") {
var projectId = projects[project].id;
var listItem = "<li><a class=\"project-link\" id=\""+projects[project].project+"\" href=\"#\">" + projects[project].project + "</a></li>";
projectList.innerHTML += listItem;
} // if !DNU
}
// ADD EVENT LISTENERS
var projLink = document.getElementsByClassName("project-link");
for (var i = 0; i < projLink.length; i++) {
var projId = projLink[i].id;
//projLink[i].dataset.projIx = [i];
projLink[i].addEventListener("click", showProject, false);
}
var showNext = document.getElementById("show-next");
var showPrev = document.getElementById("show-previous");
showNext.addEventListener("click", showProject, false);
showPrev.addEventListener("click", showProject, false);
// ARROW KEYS [not invoking the showProject function]
$(document).keydown(function(e) {
if(e.which==37) { // LEFT arrow
$(showPrev).click(showProject);
console.log("previous");
} else
if(e.which==39) { // RIGHT arrow
$(showNext).click(showProject);
console.log("next");
}
})
function showProject(projId) {
var intro = document.getElementById("intro");
if (intro) {
intro.parentNode.removeChild(intro);
}
projId.preventDefault();
var projLinks = document.getElementsByClassName("project-link"); // array
var selIx = $(".selected").index();
// ###### CLICK PREVIOUS/NEXT ######
if (this.id === "show-previous" || this.id === "show-next") {
// 1a. if nothing is .selected
if (selIx < 0) {
if (this.id === "show-previous") {
var selIx = projLinks.length-1;
}
else if (this.id === "show-next") {
var selIx = 0;
}
}
// 1b. if .selected:
else if (selIx > -1) {
if (this.id === "show-previous") {
if (selIx === 0) { // if # first slide
selIx = projLinks.length-1;
}
else {
selIx --;
}
}
else if (this.id === "show-next") {
if (selIx === projLinks.length-1) { // if # last slide
selIx = 0;
}
else {
selIx ++;
}
}
}
var selProjLi = projLinks[selIx]; // => li
} // click previous/next
// ###### CLICK .project-link ######
else if (this.id !== "show-previous" && this.id !== "show-next") {
var selIx = $(this).closest("li").index();
}
// FADE OUT, CALLBACK: LOAD NEW PROJECT
$("#project-display").fadeTo(450, 0.0, function() {
// ###### ALL ######
$(".selected").removeClass("selected");
var projId = projLink[selIx].id;
var selProjLi = projLink[selIx].parentElement;
selProjLi.className = "selected";
var projectDisplay = document.getElementById("project-display");
// set vars for the project display elements:
var projName = document.getElementById("project-name"); // h3
var projTools = document.getElementById("project-tools");
var projNotes = document.getElementById("project-notes");
var projImages = document.getElementById("project-images");
// disappear the metadata elements 'cause sometimes they'll be empty
projTools.style.display = "none";
projNotes.style.display = "none";
testimonial.style.display = "none";
for (var project in projects) { // 'Projects array' -> project
if (projects[project].project === projId) {
var activeProj = projects[project];
projName.innerHTML = activeProj.project;
// maintain centered display of project-metadata: check for a value, else the element remains hidden
if(activeProj["tools used"]) {
projTools.style.display = "inline-block";
projTools.innerHTML = activeProj["tools used"];
}
if(activeProj.notes) {
projNotes.style.display = "inline-block";
projNotes.innerHTML = activeProj.notes;
}
if(activeProj.testimonial) {
testimonial.style.display = "inline-block";
testimonial.innerHTML = activeProj.testimonial;
}
// HOW TO ENSURE THESE ARE ALREADY LOADED ***BEFORE #project-display FADES IN***
projImages.innerHTML = "";
for (var i = 0; i < activeProj.images.length; i++ ) {
projImages.innerHTML += "<img src=\"" + activeProj.images[i].url + "\" />";
}
} // if project id ...
} // for (var obj in data)
}) // fade out
$("#project-display").fadeTo(600, 1.0);
} // showProject
} // makeLinks
function getJsonData() {
var request = ajaxReq();
request.open("GET", "/json/projects.json", true);
request.setRequestHeader("content-type", "application/json");
request.send(null);
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
//makeLinks(request.responseText);
var projects = JSON.parse(request.responseText);
var projects = projects["Projects"];
makeLinks(projects); // makeLinks = callback
return projects;
}
}
} // onreadystatechange
} // getJsonData
getJsonData(makeLinks);
You can add a load event to the images and run the fadeOut when all the images are loaded.
Since you are going to need multiple images to complete loading, I chose to keep track of which loads are complete using an array of jQuery.Deferred() objects. Once all the Deferreds are resolved then you can run the fade animation.
Here's a function that should work:
function fadeWhenReady(projImages, images) {
projImages.innerHTML = "";
var loads = []; //create holding bin for deferred calls
//create images and attach load events
for (var i = 0; i < activeProj.images.length; i++ ) {
var deferred = $.Deferred();
var img = $("<img src=\"" + activeProj.images[i].url + "\" />");
img.on("load", function() { deferred.resolve() }); //after image load, resolve deferred
loads.push(deferred.promise()); //add the deferred event to the array
img.appendTo(projImages); //append image to the page
}
//when all deferreds are resolved, then apply the fade
$.when.apply($, loads).done(function() {
$("#project-display").fadeTo(600, 1.0);
});
}
In your function showProject remove your call to $("#project-display").fadeTo(600, 1.0); and replace the lines below with a call to the fadeWhenReady function.
projImages.innerHTML = "";
for (var i = 0; i < activeProj.images.length; i++ ) {
projImages.innerHTML += "<img src=\"" + activeProj.images[i].url + "\" />";
}
P.S. You are using a strange mix of jQuery and vanilla javascript. The calls to document.getElementById() don't mind me so much, but I'd certainly recommend replacing your XMLHttpRequests with jQuery.ajax().