fancybox wrong image quantity with slick slider - javascript

I'm using fancybox to display image gallery.
I have this layout:
<div class="avatar">
<a class="avatar-item" data-fancybox="group" data-caption="Caption #1" href="img/avatars/jessica1.jpeg">
<img src="./img/avatars/jessica1.jpeg" width="145" height="145" alt="">
</a>
<a class="avatar-item" data-fancybox="group" data-caption="Caption #2" href="img/avatars/jessica2.jpeg">
<img src="./img/avatars/jessica2.jpeg" alt="">
</a>
</div>
And when I click on preview - gallery popup occurs, but it shows 4 images instead of 2. I included fancybox via data-attributes, without javascript. Tried magnific popup with gallery option - got same result.
link href attribute value and internal image src attribute are the same.
I don't have a thumbnail, display image cropped with css.
Hee is CSS:
.avatar {
&.slick-dotted.slick-slider {
margin-bottom: 0;
}
a.avatar-item {
width: 146px;
height: 146px;
display: inline-block;
}
width: 146px;
height: 146px;
border: 4px solid #FFF;
float: left;
position: relative;
overflow: hidden;
img {
height: 100%;
}
}

Found the problem. I use slick-slider before with infinite: true parameter, which creates an extra slides, so I got count slides x2

I have extended the _run function. Now duplicate images are removed from the gallery and still the correct key is returned. Furthermore I have the possibility to arrange the images in any order via data-facybox position.
So it is also possible to use the infinity version of the slick slider.
function _run(e, opts) {
var tempItems,
items = [],
newItem,
reOrder,
duplicates = false,
pos,
index = 0,
$target,
value,
instance;
// Avoid opening multiple times
if (e && e.isDefaultPrevented()) {
return;
}
e.preventDefault();
opts = opts || {};
if (e && e.data) {
opts = mergeOpts(e.data.options, opts);
}
$target = opts.$target || $(e.currentTarget).trigger("blur");
instance = $.fancybox.getInstance();
if (instance && instance.$trigger && instance.$trigger.is($target)) {
return;
}
if (opts.selector) {
tempItems = $(opts.selector);
} else {
// Get all related items and find index for clicked one
value = $target.attr("data-fancybox") || "";
if (value) {
tempItems = e.data ? e.data.items : [];
tempItems = tempItems.length ? tempItems.filter('[data-fancybox="' +
value + '"]') : $('[data-fancybox="' + value + '"]');
} else {
tempItems = [$target];
}
}
if (tempItems.length > 1) {
$.each(tempItems, function(key, item) { // prevents duplicate images in the gallery
newItem = false;
if (typeof item !== 'undefined') {
if (items.length > 0) {
var found = items.filter(function (items) { return items.href ==
item.href });
if (found.length == 0) {
newItem = true;
} else {
duplicates = true;
}
} else {
newItem = true;
}
}
if (newItem) {
// Sort if the attribute data-fancybox-pos exists
if ($(item).data('fancybox-pos')) {
reOrder = true;
pos = $(item).data('fancybox-pos') - 1;
if (pos in items) {
tempItem = items[pos];
items[pos] = item;
items.push(tempItem);
} else {
items[pos] = item;
}
} else {
items.push(item);
}
}
});
} else {
items = tempItems;
}
if (duplicates || reOrder) {
// find correct index if there were duplicates
$.each(items, function(key, item) {
if (item.href == $target[0].href) {
index = key;
}
});
} else {
index = $(items).index($target);
}
// Sometimes current item can not be found
if (index < 0) {
index = 0;
}
instance = $.fancybox.open(items, opts, index);
// Save last active element
instance.$trigger = $target;
}

Related

PhotoSwipe overlayed button click causes gallery to open

I'm trying to add a delete button overlayed on my thumbnails but when I click it the gallery is opened.
I tried adding this to try to stop the click propagating to the figure element but it didn't work:
$('body').on('click', '.delete-file-btn', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
});
var initPhotoSwipeFromDOM = function(gallerySelector) {
// parse slide data (url, title, size ...) from DOM elements
var parseThumbnailElements = function(el) {
var thumbElements = el.childNodes,
numNodes = thumbElements.length,
items = [],
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i]; // <figure> element
// include only element nodes
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0]; // <a> element
size = linkEl.getAttribute('data-size').split('x');
// create slide object
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
if(figureEl.children.length > 1) {
// <figcaption> content
item.title = figureEl.children[1].innerHTML;
}
if(linkEl.children.length > 0) {
// <img> thumbnail element, retrieving thumbnail url
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
// find nearest parent element
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
// triggers when user clicks on thumbnail
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define index via data- attribute
var clickedGallery = clickedListItem.parentNode,
childNodes = clickedListItem.parentNode.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
// parse picture index and gallery index from URL (#&pid=1&gid=2)
var photoswipeParseHash = function() {
var hash = window.location.hash.substring(1),
params = {};
if(hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if(!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if(pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
if(params.gid) {
params.gid = parseInt(params.gid, 10);
}
return params;
};
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
var pswpElement = document.querySelectorAll('.pswp')[0],
gallery,
options,
items;
items = parseThumbnailElements(galleryElement);
// define options (if needed)
options = {
// define gallery index (for URL)
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function(index) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}
};
// PhotoSwipe opened from URL
if(fromURL) {
if(options.galleryPIDs) {
// parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
options.index = j;
break;
}
}
} else {
// in URL indexes start from 1
options.index = parseInt(index, 10) - 1;
}
} else {
options.index = parseInt(index, 10);
}
// exit if index not found
if( isNaN(options.index) ) {
return;
}
if(disableAnimation) {
options.showAnimationDuration = 0;
}
// Pass data to PhotoSwipe and initialize it
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll( gallerySelector );
for(var i = 0, l = galleryElements.length; i < l; i++) {
galleryElements[i].setAttribute('data-pswp-uid', i+1);
galleryElements[i].onclick = onThumbnailsClick;
}
// Parse URL and open gallery if it contains #&pid=3&gid=1
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid, galleryElements[ hashData.gid - 1 ], true, true );
}
};
initPhotoSwipeFromDOM('.existing-files');
.existing-files {
margin: 1rem -.5rem;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.existing-files .file-container {
padding: .5rem;
text-align: center;
display: inline-block;
position: relative;
}
.delete-file-btn {
font-size: 0;
position: absolute;
display: block;
transform: scale(1);
width: 22px;
height: 22px;
border-radius: 40px;
background-color: #E2E8F0;
top: -1px;
right: -5px;
z-index: 100;
box-shadow: -2px 2px 6px 1px rgba(0, 0, 0, 0.25);
transition: background-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
.delete-file-btn::after, .delete-file-btn::before {
content: "";
display: block;
position: absolute;
width: 12px;
height: 2px;
background-color: #000000;
transform: rotate(45deg);
border-radius: 5px;
top: 10px;
left: 5px;
transition: background-color .15s ease-in-out;
}
.delete-file-btn::after {
transform: rotate(-45deg);
}
.delete-file-btn:hover, .delete-file-btn:focus, .delete-file-btn:active {
box-shadow: none;
background-color: #A0AEC0;
}
.delete-file-btn:hover::after, .delete-file-btn:hover::before, .delete-file-btn:focus::after, .delete-file-btn:focus::before, .delete-file-btn:active::after, .delete-file-btn:active::before {
background-color: #FFFFFF;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.js"></script>
<div class="existing-files">
<figure class="file-container">
<a data-size="304x171" data-turbolinks="false" class="gal" href="https://placeimg.com/304/171/nature"><img src="https://placeimg.com/304/171/nature"></a>
<a class="delete-file-btn" rel="nofollow" data-method="delete" href="#"></a>
</figure>
<figure class="file-container">
<a data-size="304x171" data-turbolinks="false" class="gal" href="https://placeimg.com/304/171/nature"><img src="https://placeimg.com/304/171/nature"></a>
<a class="delete-file-btn" rel="nofollow" data-method="delete" href="#"></a>
</figure>
</div>
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
Instead of preventing the click from propagating on elements it shouldn't I changed the script to only allow clicks on my gallery image anchor element class="gal" above. Here's the edited function from the script above.
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'A' && el.className == 'gal');
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define index via data- attribute
var clickedGallery = clickedListItem.parentNode.parentNode,
childNodes = clickedListItem.parentNode.parentNode.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem.parentNode) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};

How to remove background-color from jQuery, but apply it with CSS while making the jQuery script work?

I am using the following jQuery script from enter link description here
<script>
var calendarObjects = [
{name:"Event Type 1", colour:"#735f9e"},
{name:"Event Type 2", colour:"#0000FF"},
{name:"Event Type 3", colour:"#0066cc"},
{name:"Event Type 4", colour:"#83b53f"},
{name:"Event Type 5", colour:"#ff99cc"} ,
]
</script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript">
LoadSodByKey("SP.UI.ApplicationPages.Calendar.js", function () {
WaitForCalendarToLoad();
});
var SEPARATOR = "|||";
function WaitForCalendarToLoad() {
var _renderGrids = SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids;
SP.UI.ApplicationPages.SummaryCalendarView.prototype.renderGrids = function($p0) {
_renderGrids.call(this, $p0);
ColourCalendar();
}
var _onItemsSucceed = SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed;
SP.UI.ApplicationPages.CalendarStateHandler.prototype.onItemsSucceed = function($p0, $p1) {
_onItemsSucceed.call(this, $p0, $p1);
ColourCalendar();
}
}
function ColourCalendar() {
// Find calendar links (i.e. links that contain the separator |||)
if ($('a:contains(' + SEPARATOR + ')') != null) {
// Loop through calendar links
$('a:contains(' + SEPARATOR + ')').each(function (i) {
// Get the div of the calendar entry
$box = $(this).parents('div[title]');
// Get the category, colour and actual text
var category = GetCategory(this.innerHTML);
if (category != "")
{
var colour = GetColourCodeFromName(category);
var actualText = GetActualText(this.innerHTML);
// Set html of calendar entry
this.innerHTML = actualText;
// Set the title of the div
$($box).attr("title", GetActualText($($box).attr("title")));
// Set class of div to category without spaces
$($box).attr("class", "calendarEvent " + category.replace(/ /g, ""));
// Set the background colour
$box.css('background-color', '#da7b2f');
}
else
{
// Set html of calendar entry
this.innerHTML = GetActualText(this.innerHTML);
// Set class of div to category without spaces
$($box).attr("class", "calendarEvent");
// Set the background colour
$box.css('background-color', '#da7b2f');
}
});
}
// Setup filter links
SetupFilterLinks();
// If filter already selected
var selectedFilter = document.getElementById('hfdSelectedFilter').value;
if (selectedFilter != "") {
FilterCategory(document.getElementById('hfdSelectedFilter').value);
}
}
function GetActualText(originalText) {
var parts = originalText.split(SEPARATOR);
return parts[0] + parts[2];
}
function GetCategory(originalText) {
var parts = originalText.split(SEPARATOR);
return parts[1];
}
function GetColourCodeFromName(name) {
// Iterate calendar objects
for (var i = 0, len = calendarObjects.length; i < len; i++) {
if (calendarObjects[i].name === name)
return calendarObjects[i].colour; // Return as soon as the object is found
}
return "#999999"; // Default to dark grey
}
function FilterCategory(category) {
// Get category with no spaces
var categoryNoSpaces = category.replace(/ /g, "");
// If divs with class "calendarEvent" exist
if ($('div.calendarEvent') != null) {
// Loop through divs
$('div.calendarEvent').each(function (i) {
// Hide divs
this.style.display = "none";
});
}
// If div(s) with category class exist
if ($('div.' + categoryNoSpaces) != null) {
// Loop through divs
$('div.' + categoryNoSpaces).each(function (i) {
// Set display to block
this.style.display = "block";
});
}
// Set hidden field value
document.getElementById('hfdSelectedFilter').value = categoryNoSpaces;
// Expand all days
expandCalCheck();
// Hide collapse links
hideCollapseLinks();
}
function expandCalCheck() {
var a = $("a.ms-cal-nav", $("div.ms-acal-rootdiv:last>div")).get(0);
if (a) {
for (var r = 0; r < 6; r++) {
var a = $("a.ms-cal-nav", $("div.ms-acal-rootdiv:last>div").get(r)).get(0);
if (a)
if (a.innerText.indexOf("more") >= 0) {
a.click();
}
}
}
}
function hideCollapseLinks() {
if ($('a:contains(collapse)') != null) {
// Loop through collapse links
$('a:contains(collapse)').each(function (i) {
this.style.display = "none";
});
}
}
function ShowAllEvents() {
// If divs with class "calendarEvent" exist
if ($('div.calendarEvent') != null) {
// Loop through divs
$('div.calendarEvent').each(function (i) {
// Hide divs
this.style.display = "block";
});
// Set hidden field value
document.getElementById('hfdSelectedFilter').value = "";
}
}
function SetupFilterLinks()
{
// Variables
var filters = [];
// Loop through calendar objects
$(calendarObjects).each(function (i) {
var name = this.name;
var colour = GetColourCodeFromName(name);
// Add filters variable
filters.push("<a href='javascript:void(0)' id='" + name.replace(/ /g, "") + "' class='filterLink' style='background-color:" + colour + "' onclick='FilterCategory(\"" + name + "\")'>" + name + "</a> ");
});
// Add filters to page
$('.calendarFilters').replaceWith(filters.join(''));
$('.filters a').click(function () {
$(this).addClass('selected');
$(this).siblings().removeClass('selected');
});
}
</script>
<style>
.filters
{
margin:10px 0 0 0;
}
.filters .title
{
font-size:15px;
margin:0 5px 0 0;
}
.filters .filterLink
{
color:#ffffff !important;
padding:3px 6px 4px 6px;
display: inline-block;
margin-bottom: 5px;
}
.filters .filterLinkShowAll
{
color:#ffffff !important;
background:#666666;
}
.filters .selected
{
border:2px solid #000000 !important;
padding:1px 4px 2px 4px;
}
</style>
<input type="hidden" id="hfdSelectedFilter" name="hfdSelectedFilter">
<div class="filters">
<span class="title">Filters:</span>
Show all
<div class="calendarFilters">
<!-- -->
</div>
</div>
There is a variable that controls color
$box.css('background-color', '#da7b2f');
The problem is when I try to remove the background-color variable, it does not use the following stylesheet and just inherits the color from the table it's from. How can I incorporate this stylesheet so it works with the jQuery script?
<style>
.ms-acal-time, .ms-acal-apanel-color {
DISPLAY: none;
}
.ms-acal-color6{
background-color:#0066cc!important;
}
.ms-acal-apanel-color6{
background-color:#0066cc!important;
}
.ms-acal-color8{
background-color:#787878!important;
}
.ms-acal-apanel-color8{
background-color:#787878!important;
}
</style>

How to disable JavaScript Function when other function is running

Hi,
I'm learning/practicing to make my custom slider in JS/JQuery, and I've written below code. Its almost running well but little issues. What I'm doing is I'm running it two types,
Auto running after each 5 seconds with autoRun() Function
On every click to slider indicator run to relevant slide with click event.
In below code, I'm facing couple of issues, and will be very thankful to you if you help me.
Issues I'm facing are:
When I click to slider indicator, I want to disable auto Run function for a specific time like 5 second so my slider look more professional.
When it goes to last slide or come back to first slide, console is showing an error below, and it also take double time eg: 10 seconds to go next slide.
"Uncaught TypeError: Cannot read property 'left' of undefined"
$(function () {
var $mainSliderWrap = $('#slider_main_wrapper')
, $sliderMain = $mainSliderWrap.find('.main-slider')
, $sliderchildren = $sliderMain.children('li')
, $sliderIndicator = $mainSliderWrap.find('.slider-main-indicator');
// Slider Setup
window.addEventListener('resize', initMainSlider);
initMainSlider();
// Slider SetUp function
function initMainSlider() {
var wWidth = window.outerWidth
, sliderMainWidth = wWidth * $sliderchildren.length
$sliderMain.css('width', sliderMainWidth + 'px');
$sliderMain.children('li').first().addClass('visible');
$sliderIndicator.children('li').first().addClass('active');
}
// Want to Run Slider on Click event
$sliderIndicator.on('click', 'li', updateMainSlider);
// If Click Event Not happenening then I want to auto run Slider after 5 seconds
autoRun()
function autoRun() {
var mainSliderChildLenght = $sliderchildren.length;
var i = 0;
var next = true;
var dir;
setInterval(function () {
if (mainSliderChildLenght == i || i < 0) {
next = !next;
if (i < 0) {
i = 0;
}
}
if (next) {
dir = 'next';
i++;
}
else {
dir = 'prev';
i--;
if(i < 0) {
return
}
}
updateMainSlider(dir);
$('#result').text(i)
}, 5000);
}
// Here is the function for Updating the Slider
function updateMainSlider(a) {
var visibleSlide = $sliderchildren.filter('.visible')
, actualTranslate = getTranslateValue($sliderMain, 'X');
if (a == 'next' || a == 'prev') { // inside this if is running when function is called from autoRun()
console.log(a)
var newSlide = (a == 'next') ? visibleSlide.next() : visibleSlide.prev()
, newSlideOffsetLeft = newSlide.offset().left
, valueToTranslte = -newSlideOffsetLeft + actualTranslate;
setTranslateValue($sliderMain, 'translateX', valueToTranslte);
visibleSlide.removeClass('visible');
newSlide.addClass('visible');
$sliderIndicator.children('.active').removeClass('active');
$sliderIndicator.find('li').eq(newSlide.index()).addClass('active');
}
else { // inside this if is running when function is called from click event
console.log(a)
var newSlide = $(a.target)
, $newSlideIndicatorIndex = newSlide.index()
, $visibleSlideIndex = visibleSlide.index();
if ($newSlideIndicatorIndex !== $visibleSlideIndex && !$($sliderIndicator).hasClass('disable-click')) {
$($sliderIndicator).addClass('disable-click');
setTimeout(function () {
$($sliderIndicator).removeClass('disable-click');
}, 1000);
var diff = $newSlideIndicatorIndex - $visibleSlideIndex
, valueToTranslte = -(diff * window.outerWidth) + actualTranslate;
setTranslateValue($sliderMain, 'translateX', valueToTranslte);
$($sliderchildren[$visibleSlideIndex]).removeClass('visible');
$($sliderchildren[$newSlideIndicatorIndex]).addClass('visible');
$sliderIndicator.children('.active').removeClass('active');
$sliderIndicator.find('li').eq($newSlideIndicatorIndex).addClass('active');
} // end if
} // end else
} // end function
// SetTranslate Value Fucntion
function setTranslateValue(element, property, value) {
$(element).css({
'transform': property + '(' + value + 'px)'
});
}
// Get Translate Value function
function getTranslateValue(element, axis) {
var trValue = $(element).css('transform');
if (trValue !== 'none') {
trValue = trValue.split(')')[0];
trValue = trValue.split(',');
trValue = (axis == 'X') ? trValue[4] : trValue[5];
}
else {
trValue = 0;
}
return Number(trValue);
}
})
ol {
list-style: none;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
}
.slider-main-wrapper {
box-shadow: inset 0 0 20px orange;
min-height: 100vh;
}
ol.main-slider {
height: 85vh;
box-shadow: inset 0 0 20px green;
transition: transform 500ms ease;
}
ol.main-slider > li {
float: left;
}
ol.main-slider > li .silder-main-content {
width: 100vw;
height: 85vh;
display: flex;
justify-content: center;
align-items: center;
}
ol.main-slider > li.visible .silder-main-content {
box-shadow: inset 0 0 140px green;
}
ol.slider-main-indicator {
height: 15vh;
display: flex;
}
ol.slider-main-indicator li {
box-shadow: inset 0 0 2px green;
flex: 1;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
ol.slider-main-indicator li.active {
box-shadow: inset 0 0 80px green;
cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result" style="font-size: 30px; position: absolute;
top: 0; left: 0"></div>
<div class="slider-main-wrapper" id="slider_main_wrapper">
<ol class="main-slider">
<li>
<div class="silder-main-content">
<h1>First Slide</h1>
</div>
</li>
<li>
<div class="silder-main-content">
<h2>Second Slide</h2>
</div>
</li>
<li>
<div class="silder-main-content">
<h1>Third Slide</h1>
</div>
</li>
<li>
<div class="silder-main-content">
<h1>Fourth Slide</h1>
</div>
</li>
</ol>
<!--end slides-->
<ol class="slider-main-indicator">
<li> <span class="text">First Slide</span> </li>
<li> <span class="text">Second Slide</span> </li>
<li> <span class="text">Third Slide</span> </li>
<li> <span class="text">Fourth Slide</span> </li>
</ol>
<!--end slide indicator-->
</div>
you'll want to clearInterval when you click, the setInterval again once the processing due to the "click" event completes - so, for a start, you'll need to save the returned value of setInterval to use in clearInterval
autoRun in this code returns a function which starts the interval
this is just "part" of your code, not the whole thing - trying to keep it readable regarding the changes I have implemented
$sliderIndicator.on('click', 'li', updateMainSlider);
// save the function returned by autoRun
var go = autoRun();
// start autoRun
go();
// add a variable to store interval identifier
var interval;
function autoRun() {
var mainSliderChildLenght = $sliderchildren.length;
var i = 0;
var next = true;
var dir;
// return a function to begin autoRun for real
return function() {
// save interval identifier
interval = setInterval(function () {
// your code unchanged
}, 5000);
};
}
function updateMainSlider(a) {
var visibleSlide = $sliderchildren.filter('.visible')
, actualTranslate = getTranslateValue($sliderMain, 'X');
if (a == 'next' || a == 'prev') {
// your code - unchanged
} else {
// clear interval
clearInterval(interval);
// your code - unchanged
// now add this to restart the interval
go();
}
}
You may still need to tweak some things, I haven't gone through your code in depth
as requested
$(function () {
var $mainSliderWrap = $('#slider_main_wrapper')
, $sliderMain = $mainSliderWrap.find('.main-slider')
, $sliderchildren = $sliderMain.children('li')
, $sliderIndicator = $mainSliderWrap.find('.slider-main-indicator');
// Slider Setup
window.addEventListener('resize', initMainSlider);
initMainSlider();
// Slider SetUp function
function initMainSlider() {
var wWidth = window.outerWidth
, sliderMainWidth = wWidth * $sliderchildren.length
$sliderMain.css('width', sliderMainWidth + 'px');
$sliderMain.children('li').first().addClass('visible');
$sliderIndicator.children('li').first().addClass('active');
}
// Want to Run Slider on Click event
$sliderIndicator.on('click', 'li', updateMainSlider);
// If Click Event Not happenening then I want to auto run Slider after 5 seconds
var go = autoRun();
// start autoRun
go();
var interval;
function autoRun() {
var mainSliderChildLenght = $sliderchildren.length;
var i = 0;
var next = true;
var dir;
return function() {
setInterval(function () {
if (mainSliderChildLenght == i || i < 0) {
next = !next;
if (i < 0) {
i = 0;
}
}
if (next) {
dir = 'next';
i++;
}
else {
dir = 'prev';
i--;
if(i < 0) {
return
}
}
updateMainSlider(dir);
$('#result').text(i)
}, 5000);
});
}
// Here is the function for Updating the Slider
function updateMainSlider(a) {
var visibleSlide = $sliderchildren.filter('.visible')
, actualTranslate = getTranslateValue($sliderMain, 'X');
if (a == 'next' || a == 'prev') { // inside this if is running when function is called from autoRun()
console.log(a)
var newSlide = (a == 'next') ? visibleSlide.next() : visibleSlide.prev()
, newSlideOffsetLeft = newSlide.offset().left
, valueToTranslte = -newSlideOffsetLeft + actualTranslate;
setTranslateValue($sliderMain, 'translateX', valueToTranslte);
visibleSlide.removeClass('visible');
newSlide.addClass('visible');
$sliderIndicator.children('.active').removeClass('active');
$sliderIndicator.find('li').eq(newSlide.index()).addClass('active');
}
else { // inside this if is running when function is called from click event
clearInterval(interval);
console.log(a)
var newSlide = $(a.target)
, $newSlideIndicatorIndex = newSlide.index()
, $visibleSlideIndex = visibleSlide.index();
if ($newSlideIndicatorIndex !== $visibleSlideIndex && !$($sliderIndicator).hasClass('disable-click')) {
$($sliderIndicator).addClass('disable-click');
setTimeout(function () {
$($sliderIndicator).removeClass('disable-click');
}, 1000);
var diff = $newSlideIndicatorIndex - $visibleSlideIndex
, valueToTranslte = -(diff * window.outerWidth) + actualTranslate;
setTranslateValue($sliderMain, 'translateX', valueToTranslte);
$($sliderchildren[$visibleSlideIndex]).removeClass('visible');
$($sliderchildren[$newSlideIndicatorIndex]).addClass('visible');
$sliderIndicator.children('.active').removeClass('active');
$sliderIndicator.find('li').eq($newSlideIndicatorIndex).addClass('active');
} // end if
go();
} // end else
} // end function
// SetTranslate Value Fucntion
function setTranslateValue(element, property, value) {
$(element).css({
'transform': property + '(' + value + 'px)'
});
}
// Get Translate Value function
function getTranslateValue(element, axis) {
var trValue = $(element).css('transform');
if (trValue !== 'none') {
trValue = trValue.split(')')[0];
trValue = trValue.split(',');
trValue = (axis == 'X') ? trValue[4] : trValue[5];
}
else {
trValue = 0;
}
return Number(trValue);
}
})

How to define a variable of multiple variables in JavaScript

I would like to know how can I define a bigger variable for a set of variables that I have in javascript: showFootnotesPanel();, showReferencesPanel();, showImagesPanel();, showInformationPanel();.
Would it be something like this?
function showPanel() {
var x = [showFootnotesPanel();showReferencesPanel();showImagesPanel();showInformationPanel();]
}
Update:
I have this function that used to open a side panel on the right side and color the content:
var els = document.getElementsByClassName('change-color'),
target = document.getElementsByClassName('resources'),
changeColor = function(a) {
elements = document.getElementsByClassName("note");
for (var i = 0; i < elements.length; i++) {
console.log(elements[i])
elements[i].style.backgroundColor = "";
}
target = a.getAttribute('href');
element = document.querySelector('[data-id="' + target.substring(1, target.length) + '"]');
element.style.backgroundColor = a.getAttribute('data-color');
};
for (var i = els.length - 1; i >= 0; --i) {
els[i].onclick = function() {
showFootnotesPanel();
changeColor(this);
}
Now I have 4 side panels that need to respond to the same script, and I thought that by defining something like showPanel() is showFootnotesPanel() or showReferencesPanel() or showImagesPanel() or showInformationPanel() I might simplify things, so the last line of the script would be this instead just:
els[i].onclick = function(){showPanel();changeColor(this);}
Update 2:
Or is it possible to do this with the logical operator OR?
els[i].onclick = function(){showFootnotesPanel(); || showReferencesPanel(); || showImagesPanel(); || showInformationPanel();changeColor(this);}
Update 3:
This is the new script that I am using to hide and show the panels:
function showPanel(myPanel) {
var elem = document.getElementById(myPanel);
if (elem.classList) {
console.log("classList supported");
elem.classList.toggle("show");
} else {
var classes = elem.className;
if (classes.indexOf("show") >= 0) {
elem.className = classes.replace("show", "");
} else {
elem.className = classes + " show";
}
console.log(elem.className);
}
}
function hideOthers(one, two, three, four) {
if (one > "") {
var elem1 = document.getElementById(one);
var classes = elem1.className;
elem1.className = classes.replace("show", "");
}
if (two > "") {
var elem2 = document.getElementById(two);
var classes = elem2.className;
elem2.className = classes.replace("show", "");
}
if (three > "") {
var elem3 = document.getElementById(three);
var classes = elem3.className;
elem3.className = classes.replace("show", "");
}
if (four > "") {
var elem4 = document.getElementById(four);
var classes = elem4.className;
elem4.className = classes.replace("show", "");
}
return;
}
And this is the script that calls the panels and highlights the text on them:
var els = document.getElementsByClassName('change-color'),
target = document.getElementsByClassName('resources'),
changeColor = function(a) {
elements = document.getElementsByClassName("note");
for (var i = 0; i < elements.length; i++) {
console.log(elements[i])
elements[i].style.backgroundColor = "";
}
target = a.getAttribute('href');
element = document.querySelector('[data-id="' + target.substring(1, target.length) + '"]');
element.style.backgroundColor = a.getAttribute('data-color');
};
for (var i = els.length - 1; i >= 0; --i) {
els[i].onclick = function() {
hideOthers('footnotes-section', 'references-section', 'images-section', 'information-section');
showPanel('references-section');
changeColor(this);
}
}
Thank you!
Updated with a final solution.
In javascript you can declare variables by this way:
var text = ""; // String variable.
var number = 0; //Numeric variable.
var boolValue = true; //Boolean variable.
var arrayValue = []; // Array variable. This array can contain objects {}.
var obj = {}; // Object variable.
Check this version of your code.
// var text = ""; => String variable.
// var number = 0; => Numeric variable.
// var boolValue = true; => Boolean variable.
// var arrayValue = []; => Array variable. This array can contain objects {}.
// var obj = {}; => Object variable.
// This section of code is only to explain the first question.
(function() {
function showFootnotesPanel() {
return 10; // Random value.
}
function showReferencesPanel() {
return 30; // Random value.
}
function showImagesPanel() {
return 50; // Random value.
}
function showInformationPanel() {
return 90; // Random value.
}
function showPanel() {
return [
showFootnotesPanel(), // Index = 0
showReferencesPanel(), // Index = 1
showImagesPanel(), // Index = 2
showInformationPanel() // Index = 3
];
}
var bigVariable = showPanel(); // bigVariable is array of numeric values.
// Using logical operator to check status of variable about this demo code.
if (bigVariable[0] === 10 || bigVariable[1] === 30) {
console.log("Hey, with these values can show the FootnotesPanel and ReferencesPanel.");
} else {
console.log("With the current values can't show anything...");
}
console.log(bigVariable);
})();
// https://jsfiddle.net/dannyjhonston/t5e8g22b/
// This section of code attempts to answer the question of this post.
(function() {
// This function can be executed when the page is loaded.
function showPanel(panels) {
var panel, panelVisible = "";
var selPanels = document.getElementById("selPanels");
// In panels array...
for (var i = 0; i < panels.length; i++) {
// panels[0] = "ReferencesPanel";
panel = document.getElementById(panels[i]); // Get in the DOM tag context of the panel to set in the variable "panel".
panelVisible = panel.getAttribute("data-visible"); // HTML5 data attribute.
if (panelVisible == "true") {
panel.setAttribute("class", "show");
} else {
panel.setAttribute("class", "hide");
}
}
}
// This function is for set panel visibilty.
function setPanel(panelId, status) {
panel = document.getElementById(panelId);
panel.setAttribute("data-visible", status);
// Calling the showPanel function to check in the DOM.
showPanel(["ReferencesPanel", "InformationPanel", "ImagesPanel", "FootnotesPanel"]);
}
// Binding the change event to the select tag.
selPanels.addEventListener("change", function() {
// Executes setPanel function with panelId and true to update the data-visible attribute in the DOM.
setPanel(this.options[this.selectedIndex].value, "true");
});
// Executes showPanel function with array argument with panels Id. You need to specify every panel that want to handle.
showPanel(["ReferencesPanel", "InformationPanel", "ImagesPanel", "FootnotesPanel"]);
})();
#global {
border: solid 1px #6291AD;
}
.tools {
background-image: linear-gradient(#FFFFFF, #8999CE);
}
#global div[data-visible] {
height: 80px;
padding: 5px 0;
}
#global div p {
padding: 10px;
}
#ReferencesPanel {
background-image: linear-gradient(#FFFFFF, #FD9A9A);
float: left;
width: 20%;
}
#InformationPanel {
background-image: linear-gradient(#FFFFFF, #A1C7F1);
float: left;
width: 80%;
}
#ImagesPanel {
background-image: linear-gradient(#C6E9FB, #FFF);
width: 100%;
}
#FootnotesPanel {
background-image: linear-gradient(#C6E999, #FFF);
width: 100%;
}
.clear {
clear: both;
}
.show {
display: block;
}
.hide {
display: none;
}
<div id="global">
<div class="tools">Show Panel:
<br />
<!-- Demo -->
<select id="selPanels">
<option value="">[SELECT]</option>
<option value="ReferencesPanel">ReferencesPanel</option>
<option value="InformationPanel">InformationPanel</option>
<option value="ImagesPanel">ImagesPanel</option>
<option value="FootnotesPanel">FootnotesPanel</option>
</select>
</div>
<!-- You need to set data-visible attribute with true or false to show or hide a panel. -->
<div id="ReferencesPanel" data-visible="false">
<p>References Panel</p>
</div>
<div id="InformationPanel" data-visible="false">
<p>Information Panel</p>
</div>
<div class="clear"></div>
<div id="ImagesPanel" data-visible="false">
<p>Images Panel</p>
</div>
<div id="FootnotesPanel" data-visible="false">
<p>Foot notes Panel</p>
</div>
</div>
I dont understand your question exactly, but if you want to define a variable that contains other variables then you can use an object.
e.g:
var footNotesPanel = true;
var referencesPanel = true;
var imagesPanel = true;
var showPanels = {
footNotesPanel: footNotesPanel,
referencesPanel: referencesPanel,
imagesPanel: imagesPanel
}
/*
Option 2 - for showing/hiding side panels
1 ) create all your panels as they would appear, with all the data, but hide them with display:none;
2 ) call show panel function to show a panel.
*/
var showPanel(panel_id) {
var panel_element = $("#" + panel_id); /*panel that you want to show ( is hidden atm but somewhere on the page */
if (!panel_element.length) {
return false; //no panel with this id currently on page
} else {
//check the panel id and do some custom editing if needed, eg.
if (panel_id == "main_side_panel") {
//add some additional classes to body element etc
}
panel_element.show();
//Or Another option that you probably are looking for is below
if (panel_id == "footnotes_panel") {
showFootnotesPanel();
} else if (panel_id == "images_panel") {
showImagesPanel();
}
}
}
// And use it like this:
<div id="footnotes_panel" onclick="showPanel('footnotes_panel')"></div>
// Or simply get the element id from `event.target` and use `showPanel()` without arguments.

.hover() seems to overwrite .click()

A little background of my problem:
I'm making a board-based game when the user is going to be able to make a path from a square to another one, the thing is that when a square is clicked it should stay highlighted no matter if pointer is over of it and then leaves it. It seems when the square is clicked and then the pointer leaves it the handlerIn of .hover() changes the state of the square's path-type attribute making possible to the square to be unhighlited when the pointer enter and leaves the square.
this is what I've got so far:
$(function() {
$('td.soccer-field').click(function(){
if ($('#dice1').text() != '' && $('#dice2').text() != '') {
if ($("[path-type='begin-path']").length == 0) {
$(this).attr('path-type','begin-path');
} else if ($("[path-type='begin-path']").length && $(this).attr('path-type') != 'end-path'){
$(this).attr('path-type','end-path');
$('[path-type="selecting-actual-path"]').attr('path-type','actual-path');
} else if ($(this).attr('path-type') == 'end-path'){
$(this).attr('path-type','');
};
}
});
$('td.soccer-field').hover(
function () {
if ($('#dice1').text() != '' && $('#dice2').text() != '') {
if ($("[path-type='begin-path']").length == 0) {
$(this).attr('path-type','select-begin-path');
} else if ($(this).attr('path-type') == ''){
var actualCell = $(this).attr('id') + $(this).parent().attr('id');
var cell, distance,dicesResult = parseInt($('#dice1').text())+ parseInt($('#dice2').text());
$("[path-type*='path']").each(function () {
cell = $(this).attr('id') + $(this).parent().attr('id');
distance = new Board().calculateDistanceSquares(actualCell,cell);
if (distance == 1 && $("[path-type='selecting-actual-path']").length < (dicesResult -2))
{
$(this).attr('path-type','selecting-actual-path');
return false;
}
});
}
};
},function () {
if ($(this).attr('path-type') == 'selecting-actual-path' || $(this).attr('path-type') == 'select-begin-path') {
$(this).attr('path-type','');
}
});
$('#diceRoller').click(function() {
$('#dice1').text(Math.floor(Math.random()*6)+1);
$('#dice2').text(Math.floor(Math.random()*6)+1);
$(this).attr('disabled',true);
});
});
//function Board(playerTurn, piecesPosition, gamePhase, gameBegginingType, container)
function Board(){
this.buildBoard = function (container) {
var board = $('<table></table>').attr('id','board');
var row, cell,containerHeight,containerWidth;
for (var i=0; i<10; i++){
row = $('<tr></tr>').attr('id',i+1);
for (var j=0; j<20; j++){
cell = $('<td></td>');
cell.attr('path-type','');
if ((j == 0 || j == 19) && (i >= 3) && (i <= 6)) {
cell.addClass('behind-goal');
}
else if ((j > 0) && (j < 19)){
cell.attr('id',String.fromCharCode(j+96));
cell.addClass("soccer-field");
};
row.append(cell);
}
board.append(row);
}
$('#'+container).append(board);
};
this.calculateHorizontalDistance = function (sq1,sq2) {
var column1 = sq1.substring(0,1).charCodeAt(0);
var column2 = sq2.substring(0,1).charCodeAt(0);
return ( Math.abs(column1-column2) );
};
this.calculateVerticalDistance = function (sq1, sq2) {
var row1 = parseInt(sq1.substring(1));
var row2 = parseInt(sq1.substring(1));
return ( Math.abs(row1-row2) );
};
this.calculateDistanceSquares = function(sq1, sq2){
return(this.calculateVerticalDistance(sq1,sq2)+this.calculateHorizontalDistance(sq1,sq2));
}
}
var board = new Board();
board.buildBoard('left');
#left table{
width: 60em;
height: 25em;
border:0.2em solid black;
border-collapse:collapse;
}
#left table tr{
height: 2.5em;
}
#left table tr td{
width: 3.33em;
}
td.soccer-field{
border: 0.1em solid black;
}
td.behind-goal{
background-color: #F8FAB4;
}
td[path-type*="path"]{
border: 0.15em solid #F8FAB4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="boardContainer">
<div id="right">
<p id="dice1"></p><p id="dice2"></p>
<button id="diceRoller">Lanzar Dados</button>
</div>
<div id="left"></div>
</div>
A little help will be really appreciate
To prevent that you can add an attribute on the element whenever it is clicked and remove it later on second click. Now in the hover handler check for this attribute on the element, if it is present(or set) then don't do anything just return from the handler.
Something like this
$('td.soccer-field').click(function(){
$(this).data('clicked', !!$(this).data('clicked'));
...
...
});
$('td.soccer-field').hover(
function () {
if ($(this).data('clicked')) return;
...
...
},
function () {
if ($(this).data('clicked')) return;
...
...
});

Categories

Resources