Photoswipe does not close properly in this implementation [with Slick Carousel] - photoswipe

I'm experiencing a problem that seems to be reproduced randomly after closing Photoswipe when there is more than one image in the Slick carousel. Visually, the effect is that Photoswipe closes (disappears without any animation), then the right side of the page changes again to black with last photo viewed in Photoswipe visible, then the black background fades to transparent but seems to be still there (it prevents any buttons from being clicked).
In case it's relevant, the Photoswipe open animation don't behave like the demos either - it doesn't zoom in from the thumbnail, it just simply fades in from the center of the page.
Image of the page after problem occurs: https://i.imgur.com/a4XEMxU.png
Here is my implementation using Slick and Photoswipe together:
var carousel = $('#sc');
var pswpImages = [];
var options = {
history: false
};
var count = 0;
for (var fn in data.images) {
var pieces = fn.split('.');
var fullsize = meta_data['media'] + fn;
var thumbnail = meta_data['cache'] + pieces[0] + '_m.' + pieces[1];
carousel.append('<div><img src="' + thumbnail + '" class="sc" data-id="' + count + '"></div>');
count += 1;
$('.sc').each(function () {
$(this).on('click', function () {
options.index = $(this).data('id');
var pswpElement = document.querySelectorAll('.pswp')[0];
var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, pswpImages, options);
gallery.init();
})
});
pswpImages.push({
src: fullsize,
msrc: thumbnail,
w: data.images[fn]['x'],
h: data.images[fn]['y']
});
}
// TODO: When closing gallery, get image number, and slick.GoTo that slide
carousel.slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
variableWidth: true,
centerMode: true
});

Could you provide a fiddle?
I suspect the $('.sc').each(function () needs to be outside the for loop, otherwise you are creating an on click event for every img previously created by the for loop.
1st iteration:
create 1 div, .each( ..on('click')) on that 1 img
2nd iteration:
create 2nd div, .each( ..on('click')) on the first AND the second img
..and so on.
So, in the end: clicking an image will start multiple instances of PhotoSwipe, but only if there are more than 1 images - just like you observed. The first iteration ist still fine.
A simple fix could be to call .off() before .on(), like:
...
$('.sc').each(function () {
$(this).off().on('click', function () {
options.index = $(this).data('id');
...

Related

Add content before and after table (jsPDF autotable)

i have a question to jsPDF autotable.
My Code:
$('#printBtn').on('click', function() {
var pdf = new jsPDF('p', 'pt', 'a4');
var res = pdf.autoTableHtmlToJson(document.getElementById("tablePrint"));
pdf.autoTable(res.columns, res.data, {
theme : 'plain',
styles: {
fontSize: 12
},
showHeader: 'never',
createdCell: function(cell, data) {
var tdElement = cell.raw;
if (tdElement.classList.contains('hrow')) {
cell.styles.fontStyle = 'bold';
}
}
});
pdf.save("test.pdf");
});
I want add Text before and after the Table from a div.
I have found this Code Snippet in jsPDF autotable examples:
var before = "text before";
pdf.text(before, 14, 30);
This code works good. I have insert that before pdf.autoTable(...});.
But i dont know what the number 14 and 30 for?
Then i have the code insert after the pdf.autoTable function call and the Text printed on the last page of pdf but on the top of the page, not on the end, why?
Sorry for my bad englisch.
Thanks for help.
If what you want is to add something before you must first move the table that you are adding with autotable, you achieve this by adding a startY: 150 attribute within doc.autotable:
pdf.autoTable(res.columns, res.data, {
theme : 'plain',
styles: {
fontSize: 12
},
startY: 150,
showHeader: 'never',
createdCell: function(cell, data) {
var tdElement = cell.raw;
if (tdElement.classList.contains('hrow')) {
cell.styles.fontStyle = 'bold';
}
}
});
150 is the value in pixels you want to move. Above this you can place the text you want with the code you placed.
var before = "text before";
pdf.text(before, 14, 30);
Now the values of 14 (Value in Y) and 30 (Value in Y) are the values that you want the text to move in pixels.
In order for you to add text after the table you must first obtain in which number of pixels your table ended and from there enter the text you want.
let finalY = pdf.previousAutoTable.finalY; //this gives you the value of the end-y-axis-position of the previous autotable.
pdf.text("Text to be shown relative to the table", 12, finalY + 10); //you use the variable and add the number of pixels you want it to move.
Here's my stab at an answer:
So this is your Autotable's function call:
var pdf = new jsPDF('p', 'pt', 'a4');
Since jsPDF Autotables is based on jsPDF, you'll have to go here:
pt is a unit of measurement called points, so 14 and 30 are points. At the first position, 14, moves elements left and right. The second position, 30, moves elements down and up. I'm guessing they're like pixels(px). Seems like you have to move your text to your desired locations by using points.
An idea that helped me is to placing a Table with no content on the position where you would like to add the new table.
autoTable(doc, {
body: [],
startY: finalY + bias
});

Scrolling <div> in iOS causes div to blank out

I'm trying to handle a long list of <div>s and maintain scroll position in the list after navigating off and coming back. Essentially when a selection made is in the list I capture the listScrollPos and then try to reset it when I'm returning to the page (in Angular - so the list is re-rendered first).
vm.getAlbums = function() {
albumService.getAlbums()
.success(function (data) {
vm.albums = data;
$timeout(function () {
if (albumService.listScrollPos) {
$("#MainView").scrollTop(albumService.listScrollPos);
albumService.listScrollPos = 0;
}
}, 50); // delay required
})
.error(function(err) {
vm.error.error(err.message);
});
};
The process works fine in all browsers I tested - except on iOS in a WebView (Safari works fine). In other browsers the list displays and the scroll position is moved after the initial render. The pointer resets and all is good.
However, on iOS 8 either in Safari or a Web View in Cordova, the div turns white and shows 'empty'. If I touch the div anywhere it immediately displays at the correct scroll position.
IOW, the DOM appears to be updated and rendered, but the browser is somehow optimizing the scrolled content that was moved under program control.
Is there any way to force the browser to re-render the element after the scroll position was moved programmatically?
Ok, so after a bit more checking the problem is definitely isolated to the iOS WebView - Safari on iOS works fine without any of the following. But a Cordova app or a pinned iOS app exhibits this 'white out' behavior.
The workaround is to explicitly force the DOM to re-render the element using the 'scrollHeight reading trick'.
Here's the code that works:
vm.getAlbums = function() {
albumService.getAlbums()
.success(function (data) {
vm.albums = data;
setTimeout(function () {
if (albumService.listScrollPos) {
var el = $("#MainView");
el.scrollTop(albumService.listScrollPos);
albumService.listScrollPos = 0;
$timeout(function() {
var t = el[0].scrollHeight;
}, 1);
}
}, 1); // delay around animation 900
})
};
Notice the last $timeout() block that simply reads the scrollHeight of the element, which forces the re-render and properly displays the result.
There's a little jumpiness due to the slight rendering delay.

Reusable Panel from hiddenDOMWindow

I have a CustomizableUI.jsm button i add to the toolbar. On click of this it opens a panel which has a chrome page loaded.
I want all windows to open this same panel. So my thought was to add the panel to Services.appShell.hiddenDOMWindow and then open it anchored to the the CustomizableUI.jsm button.
However I'm having trouble adding the panel to the hidddenDOMWindow.
This code works fine from scratchpad if you make the first line be var win = window. But if you make it be var win = Services.appShell.hiddenDOMWindow it has trouble appending the panel to the popupset. So weird.
Code here is the appShell hidden window code. If you make it var win= window it works fine:
var win = window; //Services.appShell.hiddenDOMWindow;
var panel = win.document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul','panel');
var props = {
type: 'arrow',
style: 'width:300px;height:100px;'
}
for (var p in props) {
panel.setAttribute(p, props[p]);
}
var popupset = win.document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul','popupset');
popupset.appendChild(panel);
win.document.documentElement.appendChild(popupset);
panel.addEventListener('popuphiding', function (e) {
e.preventDefault();
e.stopPropagation();
//panel.removeEventListener('popuphiding', arguments.callee, false); //if dont have this then cant do hidepopup after animation as hiding will be prevented
panel.addEventListener('transitionend', function () {
panel.hidePopup(); //just hide it, if want this then comment out line 19 also uncomment line 16
//panel.parentNode.removeChild(panel); //remove it from dom //if want this then comment out line 18
}, false);
panel.ownerDocument.getAnonymousNodes(panel)[0].setAttribute('style', 'transform:translate(0,-50px);opacity:0.9;transition: transform 0.2s ease-in, opacity 0.15s ease-in');
}, false);
panel.openPopup(window.document.documentElement, 'overlap', 100, 100);

3D rotation using Jquery .draggable() on 3D css element

I'm trying to figure out how to enable visitors to drag to rotate a 3D div using .draggable(). Currently the div rotates but also moves vertically and horizontally making the process touchy and unpredictable. I would like the origin of the div to stay fixed, and the "dragging" to only affect the rotation, so users can "spin" the div around to see the other sides.
here is link to the codepen: http://codepen.io/armandhammer8/pen/IiBga
$('.anime').draggable({
drag: function(event, ui){
var rotateCSS = 'rotate(' + ui.position.left + 'deg)';
$(this).css({
'transform': rotateCSS,
'-moz-transform': rotateCSS,
'-webkit-transform': rotateCSS
});
Thanks in advance!
The div element is a little house:
I want to be able to spin it around
The built in functionality of draggable is giving you the problems.
It's not so hard to get the functionality by yourself and stop using draggable.
Javascript:
var offset = 0, startX;
var elem = document.getElementById("element");
$('.draggable').on('mousedown', function (e) {
startX = e.pageX - offset;
})
.on('mouseup', function() {
startX = null;
})
.on('mousemove', function (e) {
if(startX) {
offset = e.pageX - startX;
elem.style['-webkit-transform'] = 'rotateY(' + offset + 'deg)';
}
});
demo

Set z-index to dynamically generated image label to prevent overlapped label hidden from image

I am implementing drag and drop, user can drag few images and drop them in a div, and I dynamically append a p tag as label to each image once user click on a button.
Currently I meet problem when I have 2 images which is very close to each other (one is on top of another). The appended p tag for the top images will be hidden by the bottom image. I tried to alert the z-index for each dropped image, and found out it is 'auto'. I guess I need to assign a new z-index for each div, but I tried in the function which i append the label, and it dint work as expect:
function generateLabel() {
var current = 5000;
$('#rightframe img').each(function () {
var cImgName = $(this).attr('id');
var width = $(this).width();
// To select the respective div
var temp = "div#" + cImgName;
$.ajax({
url: '/kitchen/generatelabel',
type: 'GET',
data: { containerImgName: cImgName },
async: false,
success: function (result) {
$(temp).append(result);
// I guess the each function loop through each div according to the time it is created, so I try to assign a decreasing z-index
$(temp).css('z-index', current);
current -= 100;
// To select the label for the image
temp += " p";
// Set label width based on image width
$(temp).width(width);
}
});
});
However, what I get is, bottom image which dropped later do NOT hide the label of the image above, but if the above image is dropped after than the bottom image, above image's label is hide by the bottom image.
It's a very specific situation and I hope I do make myself clear...
Hope can get some help here... Appreciate any feedback...
I am so glad that I able to work out a solution for this kinda weird problem. I get to one useful plugin, the jquery-overlaps which check 2 dom whether they are overlapped with each other or not. Then i assign a z-index to the label accordingly.
Just to show my solution here, in case anyone jump into this bottleneck :)
// To assign an increasing z-index to the label
var count = 100;
$('#rightdiv p').each(function () {
// If any label overlaps with the image (used overlaps plugin)
if ($(this).overlaps($('#rightdiv img'))) {
// Increase count (the z-index)
count += 10;
// Set the parent div z-index 1st, if not the label z-index do not have effect
$(this).parent().css('z-index', count);
$(this).css('z-index', count);
}
});
Thanks! :D

Resources