Cannot get multiple links to change single rollover to work - javascript

I can't get multiple links to work I keep getting Uncaught Reference Error:Cannot set property "imgToChange" of null(...) Could someone please tell me where I am going wrong.
"use strict";
window.onload = rolloverInit;
function rolloverInit() {
for(var i = 0;i<document.links.length;i++) {
var linkObj =document.links[i];
if(linkObj,"id") {
var linkObj =document.getElementById(linkObj.caption);
if("imgObj") {
setupRollover(linkObj,"imgObj");
}
}
}
}
function setupRollover(theLink,theImage) {
theLink.imgToChange = theImage;
theLink.onmouseout = function() {
this.imgToChange.src = this.outImage.src;
}
theLink.onmouseover = function () {
this.imgToChange.src = this.overImage.src;
}
theLink.outImage = new Image();
theLink.outImage = textImage.src;
theLink.overImage = new Image();
theLink.overImage.src = "images/" + theLink.id + "Text.gif";
}
function setupRollover(theLink,australia) {
theLink.imgToChange = "australiamap";
theLink.onmouseout = function () {
this.imgToChange.src = this.outImage.src;
}
theLink.onmouseover = function() {
this.imgToChange.src = this.overImage.src;
}
theLink.outImage = new Image();
theLink.outImage = "images/australiamap.jpg";
theLink.overImage = new Image();
theLink.overImage.src = "images/" + caption.id + "adelaide5.jpg";
}

You seem to pass null to your function, try doing a check before you call it:
function rolloverInit() {
for(var i = 0;i<document.links.length;i++) {
var linkObj =document.links[i];
if(linkObj,"id") {
var linkObj =document.getElementById(linkObj.caption);
if(linkObj !== null) { //check if linkObj is not null
setupRollover(linkObj,"imgObj");
}
}
}
}

Related

I'm trying to convert a HTML canvas to a HTML image, but I'm getting a blank image

In my application I generate a circle using the HTML element canvas.
The generation of the circle works well: the circle is correctly rendered.
The problem is that I have to put that circle in an option of a select, and as far as I know is not possible to put a canvas inside an option, therefore I probably have to convert the canvas to a base64 image so that I should be able to use it as a background-image of the option.
However, the conversion from canvas to base64 image is not working, as the browser is rendering a blank image.
I have created a fiddle for troubleshooting: https://jsfiddle.net/4hfmp0cs/
Here below you can see the javascript code of the fiddle.
function foo()
{
var circle = getStateCircle("opened");
//var gl = circle.getContext("webgl", { preserveDrawingBuffer: true });
var dataUrl = circle.toDataURL("image/png");
var img = document.createElement("img");
img.src = dataUrl;
document.getElementById("container").appendChild(img);
}
function getStateCircle(state)
{
var stateCircle;
if(state === "opened")
{
stateCircle = new Circle("#ffcc00", "20px");
}
else if(state === "accepted")
{
stateCircle = new Circle("#33cc33", "20px");
}
else if (state === "refused")
{
stateCircle = new Circle("#ff3300", "20px");
}
else if (state === "closed")
{
stateCircle = new Circle("black", "20px");
}
else
{
throw new Error("The state of the offer is unknown");
}
stateCircle.buildCircle();
var circle = stateCircle.getCircle();
return circle;
}
function Circle(color, size)
{
this._color = color;
this._size = size;
this._circle;
this.buildCircle = function()
{
var style = {
borderRadius: "50%",
backgroundColor: this._color,
height: this._size,
width: this._size
}
this._circle = new ElementBuilder("canvas").withStyleObject(style).getElement();
}
this.buildCircleAndAppendTo = function(father)
{
this._buildCircle();
father.appendChild(this._circle);
}
this.getCircle = function()
{
return this._circle;
}
}
function ElementBuilder(elementName) {
var This = this;
this.element = document.createElement(elementName);
this.withName = function (name)
{
this.element.setAttribute("name", name);
return this;
};
this.withAttribute = function (attributeName, attributeValue)
{
this.element.setAttribute(attributeName, attributeValue);
return this;
};
this.withId = function (id)
{
this.element.setAttribute("id", id);
return this;
}
this.withClass = function (className)
{
this.element.setAttribute("class", className);
return this;
}
this.addClass = function (className)
{
this.element.className = this.element.className + " " + className;
return this;
}
this.withTextContent = function (text)
{
this.element.textContent = text;
return this;
}
this.withValue = function (value)
{
this.element.value = value;
return this;
}
this.getElement = function ()
{
return this.element;
};
this.withChild = function (child)
{
this.element.appendChild(child);
return this;
};
this.withEventListener = function (type, func)
{
this.element.addEventListener(type, func);
return this;
};
this.withClickEventListener = function (func)
{
this.element.addEventListener("click", func);
return this;
}
this.withDoubleClickEventListener = function (func)
{
this.element.addEventListener("dblclick", func);
return this;
}
this.withStyle = function (styleAttribute, value)
{
this.element.style[styleAttribute] = value;
return this;
}
this.withStyleObject = function (styleObject)
{
ensureIsAnObject(styleObject);
var keys = Object.keys(styleObject);
keys.forEach(function (elt) {
This.withStyle(elt, styleObject[elt]);
});
return this;
}
}
function ensureIsAnObject(value, argumentName) {
if (!(typeof value == "object")) {
throw new Error("The argument '" + argumentName + "' should be an object, but it's type is --->" + typeof value);
}
}
The HTML code
<div id="container">
</div>
<button onclick="foo()">Append image</button>
Nowhere are you actually drawing to the canvas, just styling it with css, which is rendered separate from the canvas. You can replace the canvas with a div, or any other block element and just append that to the document to get the correct effect.
Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
Or Check in
http://jsfiddle.net/simonsarris/vgmFN/

Revealing module pattern with prototype

Te following code is fine:
var Pill = (function() {
var hideCheckPricesPill = function() {
$(HB.pillSearchBar.checkPrices).hide();
};
var hideAnyPill = function(pill) {
$(pill).hide();
};
var displaySearchBar = function() {
$("." + HB.pillSearchBar.hideSearchForm).removeClass(HB.pillSearchBar.hideSearchForm);
};
var isEditSearchPill = function(pill) {
if(pill === HB.pillSearchBar.editSearchText) {
hideCheckPricesPill();
}
else {
hideAnyPill(pill);
}
};
var isMobileSearch = function(pill) {
if(!$(pill).hasClass(HB.pillSearchBar.jsOpenMobileSearch)){
isEditSearchPill(pill);
displaySearchBar();
}
};
var addEventListenerOnPill = function(pill) {
$(pill).on('click', 'a', function() {
isMobileSearch(pill);
});
};
return {
addEventListenerOnPill: addEventListenerOnPill
}
})();
Is there a way to add a prototype functionality to one of the public functions so that it can be returned and initialized with the "new" key word?

jquery object - function undefined error

In the following function, my objects inside floatShareBar function is undefined. Do I have to init or define a var before the functions? it throws me js error : .float - function undefined.
(function($) {
.
.
.
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
floatShareBar.float()
} else {
floatShareBar.unfloat();
}
});
var floatShareBar = function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
.
.
.
})(jQuery);
You need to get an instance of that function with a self instantiating call:
var floatShareBar = (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
return this;
})();
UPDATE 1: I modified it to create an object within the function to attach those functions to, since in the previous example this refers to the window object
var floatShareBar = (function() {
var fShareBar = $('#article-share');
var instance = {};
instance.float = function() {
console.log('float');
};
instance.unfloat = function() {
console.log("unfloat");
};
return instance;
})();
UPDATE 2: You can actually just use the new keyword as well, look here for more info
var floatShareBar = new (function() {
var fShareBar = $('#article-share');
this.float = function() {
console.log('float');
};
this.unfloat = function() {
console.log("unfloat");
};
})();
Change you function to this:
$("body").on("ab.snap", function(event) {
if (event.snapPoint >= 768) {
(new floatShareBar()).float()
} else {
(new floatShareBar()).unfloat();
}
});
function floatShareBar () {
var fShareBar = $('#article-share');
this.float = function() {
console.log(
};
this.unfloat = function() {
console.log("unfloat");
};
};
you should declare functions when using var before you call them.

Javascript callback managment

I'm having trouble with designing a class which exposes its actions through callbacks. Yes my approach works for me but also seems too complex.
To illustrate the problem I've drawn the following picture. I hope it is useful for you to understand the class/model.
In my approach, I use some arrays holding user defined callback functions.
....
rocket.prototype.on = function(eventName, userFunction) {
this.callbacks[eventName].push(userFunction);
}
rocket.prototype.beforeLunch = function(){
userFunctions = this.callbacks['beforeLunch']
for(var i in userFunctions)
userFunctions[i](); // calling the user function
}
rocket.prototype.lunch = function() {
this.beforeLunch();
...
}
....
var myRocket = new Rocket();
myRocket.on('beforeLunch', function() {
// do some work
console.log('the newspaper guys are taking pictures of the rocket');
});
myRocket.on('beforeLunch', function() {
// do some work
console.log('some engineers are making last checks ');
});
I'm wondering what the most used approach is. I guess I could use promises or other libraries to make this implementation more understandable. In this slide using callbacks is considered evil. http://www.slideshare.net/TrevorBurnham/sane-async-patterns
So, should I use a library such as promise or continue and enhance my approach?
var Rocket = function () {
this.timer = null;
this.velocity = 200;
this.heightMoon = 5000;
this.goingToMoon = true;
this.rocketStatus = {
velocity: null,
height: 0,
status: null
};
this.listener = {
};
}
Rocket.prototype.report = function () {
for (var i in this.rocketStatus) {
console.log(this.rocketStatus[i]);
};
};
Rocket.prototype.on = function (name,cb) {
if (this.listener[name]){
this.listener[name].push(cb);
}else{
this.listener[name] = new Array(cb);
}
};
Rocket.prototype.initListener = function (name) {
if (this.listener[name]) {
for (var i = 0; i < this.listener[name].length; i++) {
this.listener[name][i]();
}
return true;
}else{
return false;
};
}
Rocket.prototype.launch = function () {
this.initListener("beforeLaunch");
this.rocketStatus.status = "Launching";
this.move();
this.initListener("afterLaunch");
}
Rocket.prototype.move = function () {
var that = this;
that.initListener("beforeMove");
if (that.goingToMoon) {
that.rocketStatus.height += that.velocity;
}else{
that.rocketStatus.height -= that.velocity;
};
that.rocketStatus.velocity = that.velocity;
if (that.velocity != 0) {
that.rocketStatus.status = "moving";
}else{
that.rocketStatus.status = "not moving";
};
if (that.velocity >= 600){
that.crash();
return;
}
if (that.rocketStatus.height == 2000 && that.goingToMoon)
that.leaveModules();
if (that.rocketStatus.height == that.heightMoon)
that.landToMoon();
if (that.rocketStatus.height == 0 && !that.goingToMoon){
that.landToEarth();
return;
}
that.report();
that.initListener("afterMove");
that.timer = setTimeout(function () {
that.move();
},1000)
}
Rocket.prototype.stop = function () {
clearTimeout(this.timer);
this.initListener("beforeStop");
this.velocity = 0;
this.rocketStatus.status = "Stopped";
console.log(this.rocketStatus.status)
this.initListener("afterStop");
return true;
}
Rocket.prototype.crash = function () {
this.initListener("beforeCrash");
this.rocketStatus.status = "Crashed!";
this.report();
this.stop();
this.initListener("afterCrash");
}
Rocket.prototype.leaveModules = function () {
this.initListener("beforeModules");
this.rocketStatus.status = "Leaving Modules";
this.initListener("afterModules");
}
Rocket.prototype.landToMoon = function () {
this.initListener("beforeLandToMoon");
this.rocketStatus.status = "Landing to Moon";
this.goingToMoon = false;
this.initListener("afterLandToMoon");
}
Rocket.prototype.landToEarth = function () {
this.initListener("beforeLandToEarth");
this.stop();
this.rocketStatus.status = "Landing to Earth";
this.initListener("afterLandToEarth");
}
Rocket.prototype.relaunch = function () {
this.initListener("beforeRelaunch");
this.timer = null;
this.velocity = 200;
this.heightMoon = 5000;
this.goingToMoon = true;
this.rocketStatus = {
velocity: 200,
height: 0,
status: "relaunch"
};
this.launch();
this.initListener("afterRelaunch");
}
init;
var rocket = new Rocket();
rocket.on("afterLaunch", function () {console.log("launch1")})
rocket.on("afterLandToMoon", function () {console.log("land1")})
rocket.on("beforeLandToEarth", function () {console.log("land2")})
rocket.on("afterMove", function () {console.log("move1")})
rocket.on("beforeLaunch", function () {console.log("launch2")})
rocket.launch();
You can add any function before or after any event.
This is my solution for this kinda problem. I am not using any special methods anything. I was just wonder is there any good practise for this like problems. I dig some promise,deferred but i just can't able to to this. Any ideas ?

Simple function call inside module, getting NaN, huh?

Here is the module i am working on:
var FeatureRotator = (function($,global) {
var self = {},
currentFeature = 0,
images = [],
imagePrefix = "/public/images/features/",
timer = null,
totalImages = 0,
initialFeature,
interval,
blendSpeed,
element = null,
img1 = null,
img2 = null;
function setVisibleImage(iid) {
$("#img1").attr('src',images[iid].src).css('opacity',1);
$("#img2").css('opacity',0);
$(".active").removeClass("active");
$("#f"+iid).addClass("active");
}
function setCurrentImage(id) {
currentFeature = id;
setVisibleImage(id);
}
function doHoverIn(position) {
if (currentFeature === position) {
self.pause();
} else {
setCurrentImage(global.parseInt(position, 10));
self.pause();
}
}
function doHoverOut(position) {
self.unpause();
}
self.init = function(options,callback) {
var i = 0,
tempImg = null;
interval = options.interval || 5000;
blendSpeed = options.blendSpeed || 500;
element = options.element;
initialFeature = options.initialFeature || 0;
img1 = $("<img/>").attr('id','img1');
img2 = $("<img/>").attr('id','img2').css('opacity','0').css('margin-top',-options.height);
$(element).append(img1).append(img2);
totalImages = $(".feature").size();
for (i = 0;i < totalImages; i++) {
tempImg = new global.Image();
tempImg.src = imagePrefix +"feature_" + i + ".png";
images.push(tempImg);
$("#f"+i).css('background-image',
'url("'+imagePrefix+"feature_"+i+"_thumb.png"+'")')
.hover(doHoverIn($(this).attr('position'))
, doHoverOut($(this).attr('position'))
).attr('position',i);
}
setVisibleImage(initialFeature);
if (options.autoStart) {
self.start();
}
if (callback !== null) {
callback();
}
};
function updateImage() {
var active = $("#img1").css('opacity') === 1 ? "#img1" : "#img2";
var nextFeature = (currentFeature === totalImages-1 ? 0 : currentFeature+1);
if (active === "#img1") {
$("#img2").attr('src',images[nextFeature].src);
$("#img2").fadeTo(blendSpeed, 1);
$("#img1").fadeTo(blendSpeed, 0);
} else {
$("#img1").attr('src',images[nextFeature].src);
$("#img1").fadeTo(blendSpeed, 1);
$("#img2").fadeTo(blendSpeed, 0);
}
$("#f"+currentFeature).removeClass("active");
$("#f"+nextFeature).addClass("active");
currentFeature = nextFeature;
}
self.start = function() {
currentFeature = initialFeature;
setVisibleImage(currentFeature);
timer = global.setInterval(function(){
updateImage();
}, interval);
};
self.pause = function() {
global.clearTimeout(timer);
};
self.unpause = function() {
timer = global.setInterval(function(){
updateImage();
}, interval);
};
return self;
}(this.jQuery, this));
And here is how it is used on the page:
<script type="text/javascript">
// ...
$(function() {
FeatureRotator.init({
interval:5000,
element:'#intro',
autoStart:true,
height:177,
blendSpeed:1000,
initialFeature:0
});
});
</script>
The problem is, when setVisibleImage is called from the init method, the value of iid is NaN. I've stepped through the debugger and verified that 'initialFeature' is 0 when the setVisibleImage function is called, but alas, the value doesn't make it over there.
Can anyone help me determine what the problem is? I've run the code through JSLint, and it came back clean.
UPDATE
Ok here is my updated code, which works now except the fading doesnt work, the image just flips to the next one and doesn't fade smoothly anymore:
var FeatureRotator = (function($,global) {
var self = {},
currentFeature = 0,
images = [],
imagePrefix = "/public/images/features/",
timer = null,
totalImages = 0,
initialFeature = 0,
interval,
blendSpeed;
function setVisibleImage(iid) {
$("#img1").attr('src',images[iid].src).css('opacity',1);
$("#img2").css('opacity',0);
$(".active").removeClass("active");
$("#f"+iid).addClass("active");
}
function setCurrentImage(id) {
currentFeature = id;
setVisibleImage(id);
}
function doHoverIn(obj) {
var position = global.parseInt(obj.target.attributes["position"].value,10);
if (currentFeature === position) {
self.pause();
} else {
setCurrentImage(global.parseInt(position, 10));
self.pause();
}
}
function doHoverOut() {
self.unpause();
}
self.init = function(options,callback) {
var i = 0,
tempImg = null,
element = null,
img1 = null,
img2 = null;
interval = options.interval || 5000;
blendSpeed = options.blendSpeed || 500;
element = options.element;
initialFeature = options.initialFeature || 0;
img1 = $("<img/>").attr('id','img1');
img2 = $("<img/>").attr('id','img2').css('opacity','0').css('margin-top',-options.height);
$(element).append(img1).append(img2);
totalImages = $(".feature").size();
for (i = 0;i < totalImages; i++) {
tempImg = new global.Image();
tempImg.src = imagePrefix +"feature_" + i + ".png";
images.push(tempImg);
$("#f"+i).css('background-image','url("'+imagePrefix+"feature_"+i+"_thumb.png"+'")')
.hover(doHoverIn, doHoverOut)
.attr('position',i);
}
setVisibleImage(initialFeature);
if (options.autoStart) {
self.start();
}
if (typeof callback === "function") {
callback();
}
};
function updateImage() {
var active = $("#img1").css('opacity') === 1 ? "#img1" : "#img2";
var nextFeature = (currentFeature === totalImages-1 ? 0 : currentFeature+1);
if (active === "#img1") {
$("#img2").attr('src',images[nextFeature].src);
$("#img2").fadeTo(blendSpeed, 1);
$("#img1").fadeTo(blendSpeed, 0);
} else {
$("#img1").attr('src',images[nextFeature].src);
$("#img1").fadeTo(blendSpeed, 1);
$("#img2").fadeTo(blendSpeed, 0);
}
$("#f"+currentFeature).removeClass("active");
$("#f"+nextFeature).addClass("active");
currentFeature = nextFeature;
}
self.start = function() {
currentFeature = initialFeature;
setVisibleImage(currentFeature);
timer = global.setInterval(function(){
updateImage();
}, interval);
};
self.stop = function() {
global.clearTimeout(timer);
};
self.pause = function() {
global.clearTimeout(timer);
};
self.unpause = function() {
timer = global.setInterval(function(){
updateImage();
}, interval);
};
return self;
}(this.jQuery, this));
Since you're getting NaN, I'm guessing it is actually taking place from this line:
.hover(doHoverIn($(this).attr('position'))
...which calls this:
setCurrentImage(global.parseInt(position, 10)); // note the parseInt()
...which calls this:
setVisibleImage(id);
So the position being passed to parseInt is coming from $(this).attr('position'), which is likely an value that can't be parsed into a Number, so you get NaN.
Check out the value of that attribute in first line of the block for the for statement.
for (i = 0;i < totalImages; i++) {
console.log( $(this).attr('position') ); // verify the value of position
// ...

Categories

Resources