Reputation: 128
From a knockout observed array I am presenting a list of images in the browser window. When the user clicks on an image I want the image to pop out (larger) for better viewing, and then the image can be clicked again to dismiss.
I've largely got this working... BUT. The popout window always shows the first image.
HTML
<div data-bind="visible: favouritesArrayVisible">
<div class="panel-heading">
<h2 class="panel-title">Your favourites as cameras for display</h2>
</div>
<div data-bind="foreach: favouritesWithCamerasArray">
<div class="panel panel-wrapper" style="height=260px; width=%;">
<div class="panel-body" style="display:inline-block text-align:left;">
<a href="#" data-bind="click: $parent.overlayImageOpen">
<img class="camera" data-bind="attr : {src: fields.url.value}, {alt: fields.title.value}"/>
</a>
<div id="overlay"></div>
<div id="popup">
<a href="#" data-bind="click: $parent.overlayImageClose">
<img class="cameraPopup" data-bind="attr : {src: fields.url.value}, {alt: fields.title.value}"/>
<center><span data-bind="text: fields.title.value"></span></center>
</a>
</div>
<h4><span data-bind="text: fields.title.value"></span></h4>
<p><span data-bind="text: fields.url.value" style="word-wrap: break-word;"></span></p>
<div data-bind="if: fields.location.value">
<p><span data-bind="text: fields.location.value.longitude"></span>,<span data-bind="text: fields.location.value.latitude"></span></p>
</div>
<button data-bind="click: $parent.deleteFavouriteCameraByCamreaRecord" class="btn btn-primary pull-right">Delete Favourite</button>
</div>
</div>
</div>
Supporting JavaScript
self.overlayImageOpen = function(camera) {
console.log('Yes overlayImageOpen >' + camera.fields.title.value +'<');
var overlay = document.getElementById("overlay");
var popup = document.getElementById("popup");
overlay.style.display = "block";
popup.style.display = "block";
}
self.overlayImageClose = function() {
console.log('Yes overlayImageClose');
var overlay = document.getElementById("overlay");
var popup = document.getElementById("popup");
overlay.style.display = "none";
popup.style.display = "none";
}
It's like overlayImageOpen and overlayImageClose are bound to the first item in the array. I guess I want them to be dynamically bound or something like that???
Upvotes: 0
Views: 603
Reputation: 1584
You have multiple popups with the same ID - thus everytime you call one popup, getElementById will always refer to the first one defined on the page.
One way to fix, could just use event in your first example, that's passed inside click event:
<div id="overlay" class="popup"></div>
<div id="popup" class="popup-overlay">
and your js, you pass in a new argument and use it:
self.overlayImageOpen = function(camera, event) {
var overlay = event.target.parentNode.parentNode.parentNode.getElementsByClassName('popup-overlay')[0];
var popup = event.target.parentNode.parentNode.getElementsByClassName('popup')[0];
overlay.style.display = "block";
popup.style.display = "block";
}
This is not ideal, you can also pass a data attribute in your image click, then pass it to popup.
To make it more performant, I'd just use a single template that has popup in it, and then just pass data to it - such as image itself. Then you won't have all that duplication, which is slowing your render time.
Upvotes: 1
Reputation: 128
OK, I got this to work. It is all about the bindings... So the OPEN needs to pass the image (camera) as a parameter into the Javascript. This then manipulates the popup html code (replacing it) with specific references to the camera we want the image for.
Closing the image was a bit tricky as there isn't any dynamic binding (that I have found so far). and thus I left the original binding in place for that. Then I added an ID= to the "A href" and replaced the inner code. This meant that the close could bind correctly back to the java script.
This is easier to look at in the code.
HTML
<div data-bind="visible: favouritesArrayVisible">
<div id="overlay"></div>
<div class="panel-heading">
<h2 class="panel-title">Your favourites as cameras for display</h2>
</div>
<div data-bind="foreach: favouritesWithCamerasArray">
<div class="panel panel-wrapper" style="height=260px; width=%;">
<div class="panel-body" style="display:inline-block text-align:left;">
<a href="#" data-bind="click: $parent.overlayImageOpen">
<img class="camera" data-bind="attr : {src: fields.url.value}, {alt: fields.title.value}"/>
</a>
<div id="popup">
<a href="#" data-bind="click: $parent.overlayImageClose" id="popupimage">
<img class="cameraPopup" data-bind="attr : {src: fields.url.value}, {alt: fields.title.value}"/>
<center><span data-bind="text: fields.title.value"></span></center>
</a>
</div>
<h4><span data-bind="text: fields.title.value"></span></h4>
<p><span data-bind="text: fields.url.value" style="word-wrap: break-word;"></span></p>
<div data-bind="if: fields.location.value">
<p><span data-bind="text: fields.location.value.longitude"></span>,<span data-bind="text: fields.location.value.latitude"></span></p>
</div>
<button data-bind="click: $parent.deleteFavouriteCameraByCamreaRecord" class="btn btn-primary pull-right">Delete Favourite</button>
</div>
</div>
</div>
Javascript
self.overlayImageOpen = function(camera) {
console.log('Yes overlayImageOpen >' + camera.fields.title.value +'<');
var overlay = document.getElementById("overlay");
var popup = document.getElementById("popup");
var html = "<a href=\"#\" data-bind=\"click: $parent.overlayImageClose\">";
html += "<img class=\"cameraPopup\" src=\"" + camera.fields.url.value + "\" " + "alt=\"" + camera.fields.title.value + "\" />";
html += "<center>" + camera.fields.title.value + "</center>";
html += "</a>";
document.getElementById("popupimage").innerHTML = html;
overlay.style.display = "block";
popup.style.display = "block";
}
self.overlayImageClose = function() {
console.log('Yes overlayImageClose');
var overlay = document.getElementById("overlay");
var popup = document.getElementById("popup");
overlay.style.display = "none";
popup.style.display = "none";
}
Is it ugly... yes. Is there a better way ... I'd love to know.
Upvotes: 0