I'm running the JavaScript below to place horizontal scrolling text on the banner of my website. It works in one server but not another. I get the following error:
Error: 'this.mqo' is null or not an object
JavaScript:
function start() {
new mq('m1');
/* new mq('m2');
*/
mqRotate(mqr); // must come last
}
window.onload = start;
// Continuous Text Marquee
// permission to use this Javascript on your web page is granted
// provided that all of the code below in this script (including these
// comments) is used without any alteration
function objWidth(obj) {
if (obj.offsetWidth) return obj.offsetWidth;
if (obj.clip) return obj.clip.width;
return 0;
}
var mqr = [];
function mq(id) {
this.mqo = document.getElementById(id);
var wid = objWidth(this.mqo.getElementsByTagName('span')[0]) + 5;
var fulwid = objWidth(this.mqo);
var txt = this.mqo.getElementsByTagName('span')[0].innerHTML;
this.mqo.innerHTML = '';
var heit = this.mqo.style.height;
this.mqo.onmouseout = function () {
mqRotate(mqr);
};
this.mqo.onmouseover = function () {
clearTimeout(mqr[0].TO);
};
this.mqo.ary = [];
var maxw = Math.ceil(fulwid / wid) + 1;
for (var i = 0; i < maxw; i++) {
this.mqo.ary[i] = document.createElement('div');
this.mqo.ary[i].innerHTML = txt;
this.mqo.ary[i].style.position = 'absolute';
this.mqo.ary[i].style.left = (wid * i) + 'px';
this.mqo.ary[i].style.width = wid + 'px';
this.mqo.ary[i].style.height = heit;
this.mqo.appendChild(this.mqo.ary[i]);
}
mqr.push(this.mqo);
}
function mqRotate(mqr) {
if (!mqr) return;
for (var j = mqr.length - 1; j > -1; j--) {
maxa = mqr[j].ary.length;
for (var i = 0; i < maxa; i++) {
var x = mqr[j].ary[i].style;
x.left = (parseInt(x.left, 10) - 1) + 'px';
}
var y = mqr[j].ary[0].style;
if (parseInt(y.left, 10) + parseInt(y.width, 10) < 0) {
var z = mqr[j].ary.shift();
z.style.left = (parseInt(z.style.left) + parseInt(z.style.width) * maxa) + 'px';
mqr[j].ary.push(z);
}
}
mqr[0].TO = setTimeout('mqRotate(mqr)', 10);
}
The reason is most likely that there is no element with the id "m1". Place this line first in the start function to diagnose this:
alert(document.getElementById('m1'));
If it shows "[Object]" (or similar), the element exists and it's some other problem, but if it shows "undefined" it means that there is no such element in the page.
Related
I have been playing with this code for a while and I was wondering why when I try to add img’s to the array on the js code makes the images appear on DOM but also makes a bunch of Undefined elements appear, How can I just make the 15 images appear without the undefined? Thanks
enter link description here
var previous = document.getElementById('btnPrevious')
var next = document.getElementById('btnNext')
var gallery = document.getElementById('image-gallery')
var pageIndicator = document.getElementById('page')
var galleryDots = document.getElementById('gallery-dots');
var images = ["https://exoplanets.nasa.gov/internal_resources/1763/",
"https://cdn.britannica.com/56/234056-050-0AC049D7/first-image-from-James-Webb-Space-Telescope-deepest-and-sharpest-infrared-image-of-distant-universe-to-date-SMACS-0723.jpg",
"https://assets.newatlas.com/dims4/default/ac389ce/2147483647/strip/true/crop/1620x1080+150+0/resize/1200x800!/quality/90/?url=http%3A%2F%2Fnewatlas-brightspot.s3.amazonaws.com%2Farchive%2Funiverse-expanding-acceleration-1.jpg",
"https://media.newyorker.com/photos/590966ee1c7a8e33fb38d6cc/master/w_2560%2Cc_limit/Nissan-Universe-Shouts.jpg",
"https://www.thoughtco.com/thmb/NY5k_3slMRttvtS7mA0SXm2WW9Q=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/smallerAndromeda-56a8ccf15f9b58b7d0f544fa.jpg",
"https://static.scientificamerican.com/sciam/cache/file/05B8482C-0C04-4E41-859DCCED721883D2_source.jpg?w=590&h=800&7ADE2895-F6E3-4DF4-A11F51B652E9FA88",
"https://qph.cf2.quoracdn.net/main-thumb-66277237-200-huqebnzwetdsnnwvysbxemlskpcxnygf.jpeg",
"http://www.pioneertv.com/media/1090/hero_shot_1080x720.jpg?anchor=center&mode=crop&width=600&height=400&rnd=133159257140000000",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRSWFW1EpMNFM5-dbZEUUnzJkzT3KbUCeuhPHx_eseFCpPeX4Q_DIVPopjS0LeKVmKdQho&usqp=CAU",
"https://cdn.mos.cms.futurecdn.net/rwow8CCG3C3GrqHGiK8qcJ.jpg",
"https://static.wixstatic.com/media/917d103965314e2eacefed92edb6492c.jpg/v1/fill/w_640,h_356,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/917d103965314e2eacefed92edb6492c.jpg",
"https://astronomy.com/~/media/A5B9B6CF36484AB9A6FFAE136C55B355.jpg",
"https://discovery.sndimg.com/content/dam/images/discovery/fullset/2022/9/alien%20planet%20GettyImages-913058614.jpg.rend.hgtvcom.616.411.suffix/1664497398007.jpeg",
"https://images.newscientist.com/wp-content/uploads/2017/06/21180000/planet-10-orange-blue-final-small.jpg?crop=16:9,smart&width=1200&height=675&upscale=true",
"https://images.hindustantimes.com/img/2022/07/20/1600x900/Viral_Instagram_Planet_Rainbow_Nasa_1658316556293_1658316573815_1658316573815.PNG"
]
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: images[i]
});
}
var perPage = 8;
var page = 1;
var pages = Math.ceil(images.length / perPage)
// Gallery dots
for (var i = 0; i < pages; i++){
var dot = document.createElement('button')
var dotSpan = document.createElement('span')
var dotNumber = document.createTextNode(i + 1)
dot.classList.add('gallery-dot');
dot.setAttribute('data-index', i);
dotSpan.classList.add('sr-only');
dotSpan.appendChild(dotNumber);
dot.appendChild(dotSpan)
dot.addEventListener('click', function(e) {
var self = e.target
goToPage(self.getAttribute('data-index'))
})
galleryDots.appendChild(dot)
}
// Previous Button
previous.addEventListener('click', function() {
if (page === 1) {
page = 1;
} else {
page--;
showImages();
}
})
// Next Button
next.addEventListener('click', function() {
if (page < pages) {
page++;
showImages();
}
})
// Jump to page
function goToPage(index) {
index = parseInt(index);
page = index + 1;
showImages();
}
// Load images
function showImages() {
while(gallery.firstChild) gallery.removeChild(gallery.firstChild)
var offset = (page - 1) * perPage;
var dots = document.querySelectorAll('.gallery-dot');
for (var i = 0; i < dots.length; i++){
dots[i].classList.remove('active');
}
dots[page - 1].classList.add('active');
for (var i = offset; i < offset + perPage; i++) {
if ( images[i] ) {
var template = document.createElement('div');
var title = document.createElement('p');
var titleText = document.createTextNode(images[i].title);
var img = document.createElement('img');
template.classList.add('template')
img.setAttribute("src", images[i].source);
img.setAttribute('alt', images[i].title);
title.appendChild(titleText);
template.appendChild(img);
template.appendChild(title);
gallery.appendChild(template);
}
}
// Animate images
var galleryItems = document.querySelectorAll('.template')
for (var i = 0; i < galleryItems.length; i++) {
var onAnimateItemIn = animateItemIn(i);
setTimeout(onAnimateItemIn, i * 100);
}
function animateItemIn(i) {
var item = galleryItems[i];
return function() {
item.classList.add('animate');
}
}
// Update page indicator
pageIndicator.textContent = "Page " + page + " of " + pages;
}
showImages();
I checked your code and make it work with a small modification.
You are reusing the same array with the links of images and push inside the new object with the shape of { title, source }.
You just need to do this changes:
Change the name of your array of images. Something from images to arrayOfImages.
const arrayOfImages = ["https://exoplanets.nasa.gov/internal_resources/1763/", ...]
Declare an empty array before your first for loop. Make something like const images = []
On your for loop, instead of loop over the images variable, do it over the arrayOfImages variable.
const images = [];
for (var i = 0; i < 15; i++) {
images.push({
title: "Image " + (i + 1),
source: arrayOfImages[i]
});
}
With those changes, everything works for me.
Also, as a recommendation, try to avoid the var keyword. If you want more details about this, this answer is very helpful: https://stackoverflow.com/a/50335579/17101307
You can use Array#map to create a new array of objects from the array of URLS, then replace the original array.
images = images.map((x, i) => ({
title: "Image " + (i + 1),
source: x
}));
I've tried different variations, using this (topMag) function. What i want, with the function is, when i call the getElem function for an example with all the paragraphs, i want the topMag to count every paragraph's height from the top of the paragraph to the top of the document. Please someone explain to me, what is happening here when the function is called, and how to solve it.
var elem, celElem, elemTop = [], elemMag = [], elemBot = [], elemCent = [], winTop, winMag, winBot, winCent, i;
function getElem(el, cEl, fn){
if(el.length === undefined){
el = [el];
cEl = [cEl]
};
elem = el;
celElem = cEl;
for (i = 0; i<elem.length; i++){
elemTop[i] = 0;
elemMag[i] = elem[i].offsetHeight;
elemBot[i] = elemTop[i]+elemMag[i];
elemCent[i] = elemTop[i]+(elemMag[i]/2);
topMag(elem[i], i);
}
winTop = window.pageYOffset;
winMag = window.innerHeight;
winBot = winTop+winMag;
winCent = winTop+(winMag/2);
};
//the reason, why i need x: when the function is executed,
//i want to remain elem[i] to elem[i], not the body
function topMag(x, i){
elem[i] = x
if (getComputedStyle(elem[i]).position === "fixed"){
elemTop[i] = elem[i].offsetTop;
}
else{
do{
elemTop[i] += elem[i].offsetTop;
elem[i] = elem[i].offsetParent;
}
while(elem[i] != "[object HTMLBodyElement]");
elem[i] = x;
}
};
I'm writing a program in JS for checking equal angles in GeoGebra.
This is my first JS code, I used c# formerly for game programming.
The code is:
var names = ggbApplet.getAllObjectNames();
var lines = new Set();
var angles = new Set();
var groups = new Set();
for(var i=0; i<names.length; i++)
{
if(getObjectType(names[i].e)==="line")
{
lines.add(names[i]);
}
}
for(var i=0;i<lines.size;i++)
{
for(var j=0;j<i;j++)
{
var angle = new Angle(i,j);
angles.add(angle);
}
}
for(var i=0;i<angles.size;i++)
{
var thisVal = angles.get(i).value;
var placed = false;
for(var j=0;j<groups.size;j++)
{
if(groups.get(j).get(0).value===thisVal)
{
groups.get(j).add(angles.get(i));
placed = true;
}
}
if(!placed)
{
var newGroup = new Set();
newGroup.add(angles.get(i));
groups.add(newGroup);
}
}
for(var i=0;i<groups.size;i++)
{
var list="";
for(var j=0;j<groups.get(i).size;j++)
{
list = list+groups.get(i).get(j).name;
if(j != groups.get(i).size-1)
{
list = list+",";
}
}
var comm1 = "Checkbox[angle_{"+groups.get(i).get(0).value+"},{"+list+"}]";
ggbApplet.evalCommand(comm1);
var comm2 = "SetValue[angle_{"+groups.get(i).get(0).value+"}+,0]";
ggbApplet.evalCommand(comm2);
}
(function Angle (i, j)
{
this.lineA = lines.get(i);
this.lineB = lines.get(j);
this.name = "angleA_"+i+"B_"+j;
var comm3 = "angleA_"+i+"B_"+j+" = Angle["+this.lineA+","+this.lineB+"]";
ggbApplet.evalCommand(comm3);
var val = ggbApplet.getValue(this.name);
if(val>180)
{val = val-180}
this.value = val;
ggbApplet.setVisible(name,false)
});
function Set {
var elm;
this.elements=elm;
this.size=0;
}
Set.prototype.get = new function(index)
{
return this.elements[index];
}
Set.prototype.add = new function(object)
{
this.elements[this.size]=object;
this.size = this.size+1;
}
It turned out that GeoGebra does not recognize Sets so I tried to make a Set function.
Basically it collects all lines into a set, calculates the angles between them, groups them and makes checkboxes to trigger visuals.
the GeoGebra functions can be called via ggbApplet and the original Workspace commands via ggbApplet.evalCommand(String) and the Workspace commands I used are the basic Checkbox, SetValue and Angle commands.
The syntax for GeoGebra commands are:
Checkbox[ <Caption>, <List> ]
SetValue[ <Boolean|Checkbox>, <0|1> ]
Angle[ <Line>, <Line> ]
Thank you for your help!
In short, the syntax error you're running to is because of these lines of code:
function Set {
and after fixing this, new function(index) / new function(object) will also cause problems.
This isn't valid JS, you're likely looking for this:
function Set() {
this.elements = [];
this.size = 0;
}
Set.prototype.get = function(index) {
return this.elements[index];
};
Set.prototype.add = function(object) {
this.elements[this.size] = object;
this.size = this.size + 1;
};
Notice no new before each function as well.
I'm not sure what you're trying to accomplish by creating this Set object though - it looks like a wrapper for holding an array and its size, similar to how something might be implemented in C. In JavaScript, arrays can be mutated freely without worrying about memory.
Here's an untested refactor that removes the use of Set in favour of native JavaScript capabilities (mostly mutable arrays):
var names = ggbApplet.getAllObjectNames();
var lines = [];
var angles = [];
var groups = [];
for (var i = 0; i < names.length; i++) {
if (getObjectType(names[i].e) === "line") {
lines.push(names[i]);
}
}
for (var i = 0; i < lines.length; i++) {
for (var j = 0; j < i; j++) {
angles.push(new Angle(i, j));
}
}
for (var i = 0; i < angles.length; i++) {
var thisVal = angles[i].value;
var placed = false;
for (var j = 0; j < groups.length; j++) {
if (groups[j][0].value === thisVal) {
groups[j].push(angles[i]);
placed = true;
}
}
if (!placed) {
groups.push([angles[i]]);
}
}
for (var i = 0; i < groups.length; i++) {
var list = "";
for (var j = 0; j < groups[i].length; j++) {
list += groups[i][j].name;
if (j != groups[i].length - 1) {
list += ",";
}
}
var comm1 = "Checkbox[angle_{" + groups[i][0].value + "},{" + list + "}]";
ggbApplet.evalCommand(comm1);
var comm2 = "SetValue[angle_{" + groups[i][0].value + "}+,0]";
ggbApplet.evalCommand(comm2);
}
function Angle(i, j) {
this.name = "angleA_" + i + "B_" + j;
var comm3 = "angleA_" + i + "B_" + j + " = Angle[" + lines[i] + "," + lines[j] + "]";
ggbApplet.evalCommand(comm3);
var val = ggbApplet.getValue(this.name);
if (val > 180) {
val -= 180;
}
this.value = val;
ggbApplet.setVisible(name, false);
}
Hopefully this helps!
Your function definition is missing the parameter list after the function name.
Also, you're initializing the elements property to an undefined value. You need to initialize it to an empty array, so that the add method can set elements of it.
function Set() {
this.elements=[];
this.size=0;
}
function coordinate(x, y) {
this.x = x,
this.y = y
}
function generateBaracade(numBlocks) {
var coordinate = getRandomBaracadeCoordinate();
var xStyle = expandDirection.down;
var yStyle = expandDirection.right;
var xNumBlocks = findRandomFactor(numBlocks);
var yNumBlocks = numBlocks / xNumBlocks;
//figure out which way to expand the blocks
if (coordinate.x + xNumBlocks > xBlocks) {
xStyle = expandDirection.left;
} else {
xStyle = expandDirection.right;
}
if (coordinate.y + yNumBlocks > yBlocks) {
yStyle = expandDirection.down;
} else {
yStyle = expandDirection.up;
}
for (var i = 0; i <= xNumBlocks - 1; i++) {
for (var j = 0; j <= yNumBlocks - 1; j++) {
var tempBlock = Object.create(block);
tempBlock.type = "obstruction";
tempBlock.color = "grey";
tempBlock.illegalTerrain = true;
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
blockContainer[coordinate.x + (i * xStyle)][coordinate.y + (j * yStyle)] = tempBlock;
};
};
}
I get the 'Uncaught TypeError: object is not a function' on the line:
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
This is strange as I am following the mozilla guide to doing this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
EDIT: Source for getRandomBaracadeCoordinate. The return statement is exactly what I want to do, and executes without error.
function getRandomBaracadeCoordinate() {
var x = Math.floor((Math.random() * (xBlocks)));
var y = Math.floor((Math.random() * (yBlocks)));
return new coordinate(x, y);
}
You are shadowing the coordinate function by giving something else the same name on the first line of getBaracade:
var coordinate = getRandomBaracadeCoordinate();
Whatever getRandomBaracadeCoordinate() returns isn't a function, so new coordinate throws an error.
coordinate is an object containing { x, y } and initialized here:
var coordinate = getRandomBaracadeCoordinate();
tempBlock.coordinate = new coordinate(coordinate.x + (i * xStyle), coordinate.y + (j * yStyle));
Probably you mistyped new coordinate() instead of new Coordinate() (if Coordinate is a class).
You should look at the source of getRandomBaracadeCoordinate() — if it returns an object of some class, you should create an instance of this class. Otherwise, if it returns a simple { x:50, y:15 } object, you can create it inline:
tempBlock.coordinate = { x: coordinate.x + (i * xStyle), y: coordinate.y + (j * yStyle) };
I posted a similar question at the Drupal Forum, but I haven't had much luck.
I'm upgrading a site from D6 to D7. So far it's gone well, but I'm getting a Javascript error that I just can't pin down a solution for.
This is a cut down version of the whole script:
(function($) {
function sign(secret, message) {
var messageBytes = str2binb(message);
var secretBytes = str2binb(secret);
if (secretBytes.length > 16) {
secretBytes = core_sha256(secretBytes, secret.length * chrsz);
}
var ipad = Array(16), opad = Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = secretBytes[i] ^ 0x36363636;
opad[i] = secretBytes[i] ^ 0x5C5C5C5C;
}
var imsg = ipad.concat(messageBytes);
var ihash = core_sha256(imsg, 512 + message.length * chrsz);
var omsg = opad.concat(ihash);
var ohash = core_sha256(omsg, 512 + 256);
var b64hash = binb2b64(ohash);
var urlhash = encodeURIComponent(b64hash);
return urlhash;
}
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
Date.prototype.toISODate =
new Function("with (this)\nreturn " +
"getFullYear()+'-'+addZero(getMonth()+1)+'-'" +
"+addZero(getDate())+'T'+addZero(getHours())+':'" +
"+addZero(getMinutes())+':'+addZero(getSeconds())+'.000Z'");
function getNowTimeStamp() {
var time = new Date();
var gmtTime = new Date(time.getTime() + (time.getTimezoneOffset() * 60000));
return gmtTime.toISODate() ;
}
}(jQuery));
The part that keeps throwing an error I'm seeing in Firebug is at:
Date.prototype.toISODate =
new Function("with (this)\n return " +
"getFullYear()+'-'+addZero(getMonth()+1)+'-'" +
"+addZero(getDate())+'T'+addZero(getHours())+':'" +
"+addZero(getMinutes())+':'+addZero(getSeconds())+'.000Z'");
Firebug keeps stopping at "addZero is not defined". JS has never been my strong point, and I know some changes have been made in D7. I've already wrapped the entire script in "(function($) { }(jQuery));", but I must be missing something else. The same script works perfectly on the D6 site.
Here is the "fixed" version of the whole code with #Pointy suggestion added. All I left out is the part of the script for making the hash that goes to Amazon, and some of my declared variables.
(function($) {
var typedText;
var strSearch = /asin:/;
var srchASIN;
$(document).ready(function() {
$("#edit-field-game-title-und-0-asin").change(function() {
typedText = $("#edit-field-game-title-und-0-asin").val();
$.ajax({
type: 'POST',
data: {typedText: typedText},
dataType: 'text',
url: '/asin/autocomplete/',
success:function(){
document.getElementById('asin-lookup').style.display='none';
x = typedText.search(strSearch);
y = (x+5);
srchASIN = typedText.substr(y,10)
amazonSearch();
}
});
});
$("#search_asin").click(function() {
$("#edit-field-game-title-und-0-asin").val('');
document.getElementById('name-lookup').style.display='none';
$("#edit-field-game-title-und-0-asin").val('');
$("#edit-title").val('');
$("#edit-field-subtitle-und-0-value").val('');
$("#edit-field-game-edition-und-0-value").val('');
$("#edit-field-release-date-und-0-value-date").val('');
$("#edit-field-asin-und-0-asin").val('');
$("#edit-field-ean-und-0-value").val('');
$("#edit-field-amazon-results-und-0-value").val('');
$("#edit-body").val('');
srchASIN = $("#field-asin-enter").val();
amazonSearch();
});
$("#clear_search").click(function() {
$("#field-asin-enter").val('');
$("#edit-field-game-title-und-0-asin").val('');
$("#edit-title").val('');
$("#edit-field-subtitle-und-0-value").val('');
$("#edit-field-game-edition-und-0-value").val('');
$("#edit-field-release-date-und-0-value-date").val('');
$("#edit-field-release-dt2-und-0-value-date").val('');
$("#edit-field-asin-und-0-asin").val('');
$("#edit-field-ean-und-0-value").val('');
$("#edit-field-amazon-results-und-0-value").val('');
$("#field-amazon-platform").val('');
$("#field-amazon-esrb").val('');
$("#edit-body-und-0-value").val('');
document.getElementById('asin-lookup').style.display='';
document.getElementById('name-lookup').style.display='';
});
function amazonSearch(){
var ASIN = srchASIN;
var azScr = cel("script");
azScr.setAttribute("type", "text/javascript");
var requestUrl = invokeRequest(ASIN);
azScr.setAttribute("src", requestUrl);
document.getElementsByTagName("head").item(0).appendChild(azScr);
}
});
var amzJSONCallback = function(tmpData){
if(tmpData.Item){
var tmpItem = tmpData.Item;
}
$("#edit-title").val(tmpItem.title);
$("#edit-field-game-edition-und-0-value").val(tmpItem.edition);
$("#edit-field-release-date-und-0-value-date").val(tmpItem.relesdate);
$("#edit-field-release-dt2-und-0-value-date").val(tmpItem.relesdate);
$("#edit-field-asin-und-0-asin").val(tmpItem.asin);
$("#edit-field-ean-und-0-value").val(tmpItem.ean);
$("#field-amazon-platform").val(tmpItem.platform);
$("#field-amazon-publisher").val(tmpItem.publisher);
$("#field-amazon-esrb").val(tmpItem.esrb);
};
function ctn(x){ return document.createTextNode(x); }
function cel(x){ return document.createElement(x); }
function addEvent(obj,type,fn){
if (obj.addEventListener){obj.addEventListener(type,fn,false);}
else if (obj.attachEvent){obj["e"+type+fn]=fn; obj.attachEvent("on"+type,function(){obj["e"+type+fn]();});}
}
var styleXSL = "http://www.tlthost.net/sites/vglAmazonAsin.xsl";
function invokeRequest(ASIN) {
cleanASIN = ASIN.replace(/[-' ']/g,'');
var unsignedUrl = "http://xml-us.amznxslt.com/onca/xml?Service=AWSECommerceService&AssociateTag=theliterarytimes&IdType=ASIN&ItemId="+cleanASIN+"&Operation=ItemLookup&ResponseGroup=Medium,ItemAttributes,OfferFull&Style="+styleXSL+"&ContentType=text/javascript&CallBack=amzJSONCallback";
var lines = unsignedUrl.split("\n");
unsignedUrl = "";
for (var i in lines) { unsignedUrl += lines[i]; }
// find host and query portions
var urlregex = new RegExp("^http:\\/\\/(.*)\\/onca\\/xml\\?(.*)$");
var matches = urlregex.exec(unsignedUrl);
var host = matches[1].toLowerCase();
var query = matches[2];
// split the query into its constituent parts
var pairs = query.split("&");
// remove signature if already there
// remove access key id if already present
// and replace with the one user provided above
// add timestamp if not already present
pairs = cleanupRequest(pairs);
// encode the name and value in each pair
pairs = encodeNameValuePairs(pairs);
// sort them and put them back together to get the canonical query string
pairs.sort();
var canonicalQuery = pairs.join("&");
var stringToSign = "GET\n" + host + "\n/onca/xml\n" + canonicalQuery;
// calculate the signature
//var secret = getSecretAccessKey();
var signature = sign(secret, stringToSign);
// assemble the signed url
var signedUrl = "http://" + host + "/onca/xml?" + canonicalQuery + "&Signature=" + signature;
//document.write ("<html><body><pre>REQUEST: "+signedUrl+"</pre></body></html>");
return signedUrl;
}
function encodeNameValuePairs(pairs) {
for (var i = 0; i < pairs.length; i++) {
var name = "";
var value = "";
var pair = pairs[i];
var index = pair.indexOf("=");
// take care of special cases like "&foo&", "&foo=&" and "&=foo&"
if (index == -1) {
name = pair;
} else if (index == 0) {
value = pair;
} else {
name = pair.substring(0, index);
if (index < pair.length - 1) {
value = pair.substring(index + 1);
}
}
// decode and encode to make sure we undo any incorrect encoding
name = encodeURIComponent(decodeURIComponent(name));
value = value.replace(/\+/g, "%20");
value = encodeURIComponent(decodeURIComponent(value));
pairs[i] = name + "=" + value;
}
return pairs;
}
function cleanupRequest(pairs) {
var haveTimestamp = false;
var haveAwsId = false;
var nPairs = pairs.length;
var i = 0;
while (i < nPairs) {
var p = pairs[i];
if (p.search(/^Timestamp=/) != -1) {
haveTimestamp = true;
} else if (p.search(/^(AWSAccessKeyId|SubscriptionId)=/) != -1) {
pairs.splice(i, 1, "AWSAccessKeyId=" + accessKeyId);
haveAwsId = true;
} else if (p.search(/^Signature=/) != -1) {
pairs.splice(i, 1);
i--;
nPairs--;
}
i++;
}
if (!haveTimestamp) {
pairs.push("Timestamp=" + getNowTimeStamp());
}
if (!haveAwsId) {
pairs.push("AWSAccessKeyId=" + accessKeyId);
}
return pairs;
}
function sign(secret, message) {
var messageBytes = str2binb(message);
var secretBytes = str2binb(secret);
if (secretBytes.length > 16) {
secretBytes = core_sha256(secretBytes, secret.length * chrsz);
}
var ipad = Array(16), opad = Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = secretBytes[i] ^ 0x36363636;
opad[i] = secretBytes[i] ^ 0x5C5C5C5C;
}
var imsg = ipad.concat(messageBytes);
var ihash = core_sha256(imsg, 512 + message.length * chrsz);
var omsg = opad.concat(ihash);
var ohash = core_sha256(omsg, 512 + 256);
var b64hash = binb2b64(ohash);
var urlhash = encodeURIComponent(b64hash);
return urlhash;
}
Date.prototype.toISODate = function() {
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
var d = this;
return d.getFullYear() + '-' +
addZero(d.getMonth() + 1) + '-' +
addZero(d.getDate()) + 'T' +
addZero(d.getHours()) + ':' +
addZero(d.getMinutes()) + ':' +
addZero(d.getSeconds()) + '.000Z';
};
function getNowTimeStamp() {
var time = new Date();
var gmtTime = new Date(time.getTime() + (time.getTimezoneOffset() * 60000));
return gmtTime.toISODate() ;
}
}(jQuery));
Here's a better version of your code:
Date.prototype.toISODate = function() {
function addZero(n) {
return ( n < 0 || n > 9 ? "" : "0" ) + n;
}
var d = this;
return d.getFullYear() + '-' +
addZero(d.getMonth() + 1) + '-' +
addZero(d.getDate()) + 'T' +
addZero(d.getHours()) + ':' +
addZero(d.getMinutes()) + ':' +
addZero(d.getSeconds()) + '.000Z';
};
That moves "addDate" inside the extension function, and it avoids the horrid with statement.