Reputation: 136
Sorry for the poor title, hard to explain this without showing the code.
I have a javaScript class called Coupon that has a function that basically opens up a fancyBox and displays the contents of that coupon object (its dynamic).
Like so
function CouponPopup( id, title, barcodeUrl, expirationDate, description ) {
this.coupondId = id;
this.couponContainer = document.createElement('div');
this.couponTitle = document.createElement('h2');
this.couponPrizeName = document.createElement('h3');
var self = this;
// More vars, etc. . .
// assemble the coupon
this.couponContainer.appendChild(this.couponTitle);
this.couponContainer.appendChild(this.couponPrizeName);
this.couponContainer.appendChild(this.couponRevealDetails);
this.couponContainer.appendChild(this.couponBarcode);
this.couponContainer.appendChild(this.couponExpirationText);
this.couponContainer.appendChild(this.couponPrintButton);
this.show = function ( event ) {
$.fancybox(self.couponContainer);
}
}; // end class CouponPopup
Now, in a the code calling this, I am trying to make a link - that when it is clicked will call the show function on the right instance of CouponPopup.
for (var i = 0; i < dataLength; i++) {
if (data.type === "coupon") {
var couponId = "coupon_" + i;
// right now, my coupon will be on global scope.
myCoupon = new CouponPopup( couponId,
data.rewards[i].prize_name,
data.rewards[i].url,
data.rewards[i].expirationdate);
rewardInfo = '<a id="' + couponId + '" onclick="myCoupon.show( event )">View Coupon</a>';
}
}
rewardInfo eventually gets appended to a the page - and looks fine.
However, when I click on it, since myCoupon is on the globalScope - the fancyBox that is shown is always the last coupon that is created.
If I try to put myCoupon on the local scope (adding the var keyword), I get an JS error saying that myCoupon is undefined when its added to the onClick handler of the link.
What I want to do is make myCoupon a local variable and still have this work - so the onClick event of the link is tied to the specific instance of myCoupon
What is the best way to do this? I have a hack working, but its a hack and I really don't like needing to use global variables in my code if I can help it.
Having a brain fart on this one, so any help is appreciated!
Looking for an old-school ES5 solution.
Upvotes: 0
Views: 103
Reputation: 136
OK, I got it - very close to what @DimitriL sucggested - here the final code:
if (data.type === "coupon") { {
var link = ( function( i, data )
{
var couponId = "coupon_" + i;
var myCoupon = new CouponPopup(couponId,
data.rewards[i].prize_name,
data.rewards[i].url,
data.rewards[i].expirationdate);
var link = document.createElement('a');
link.id = couponId;
clickMe = function (event) {
console.log("in clickme");
myCoupon.show(event);
};
link.onclick = this.clickMe;
link.innerHTML = "View Coupon";
return link;
})( i, data );
$(reward).append(link);
}
Thanks to everyone for the help - closure and scope issues are a pain sometimes!
Upvotes: 0
Reputation: 4329
You may try doing the following :
for (var i = 0; i < dataLength; i++) {
if (data.type === "coupon") {
var couponId = "coupon_" + i;
// right now, my coupon will be on global scope.
myCoupon = new CouponPopup( couponId,
data.rewards[i].prize_name,
data.rewards[i].url,
data.rewards[i].expirationdate);
rewardInfo = '<a id="' + couponId + '" onclick="showCoupon('+ couponId +')">View Coupon</a>';
}
}
And then create a function showCoupon like this :
function showCoupon (couponId) {
try {
var index = parseInt(couponId.replace('coupon_', ''));
new CouponPopup( couponId,
data.rewards[index].prize_name,
data.rewards[index].url,
data.rewards[index].expirationdate).show();
} catch(err) { console.log("wrong coupon id ", err);}
}
Upvotes: 2
Reputation: 4879
You should create a DOM element instead of html as text and put it in a separate scope.
I have not tested this code:
for (var i = 0; i < dataLength; i++) {
if (data.type === "coupon") {
// separate scope
(function(i, data) {
var couponId = "coupon_" + i;
// local scope
var myCoupon = new CouponPopup( couponId,
data.rewards[i].prize_name,
data.rewards[i].url,
data.rewards[i].expirationdate);
// create a DOM element
var link = document.createElement('a');
link.id = couponId;
link.onclick = function(event) { myCoupon.show(event); };
link.innerHTML = 'View Coupon';
// append your link somewhere
})(i, data);
}
}
Imo the CouponPopup function should return this;
at the end, but i might be wrong.
Upvotes: 1