display events only on onclick of the day of events - javascript

I have this code im using to display events from a calendar but its displaying ALL of the events for that month and I only want to display the events for the day when a user clicks on a certain day. For example, click on February 10, you get all of the events for that day.
var eventList = $('<div/>').addClass('c-event-list');
for (var i = 0; i < settings.events.length; i++) {
var d = settings.events[i].datetime;
if ((d.getMonth() - 1) == dMonth && d.getFullYear() == dYear) {
var date = lpad(d.getMonth(), 2) + '/' +
lpad(d.getDate(), 2) + ' ' +
lpad(d.getHours() %12, 2) + ':' +
lpad(d.getMinutes(), 2);
var item = $('<div/>').addClass('c-event-item');
var title = $('<div/>')
.addClass('title')
.html(date + ' ' + settings.events[i].title + '<br />');
var description = $('<div/>')
.addClass('description')
.html(settings.events[i].description + '<br />');
item.attr('data-event-day', d.getDate());
item.on('mouseover', mouseOverItem).on('mouseleave', mouseLeaveItem);
item.append(title).append(description);
eventList.append(item);
}
}
$(instance).addClass('calendar');
cEventsBody.append(eventList);
$(instance).html(cBody).append(cEvents);
}
return print();
}
Thanks in advance for any assistance.

What I can see from your code is that this condition determines the month and year that events should be held on:
((d.getMonth() - 1) == dMonth && d.getFullYear() == dYear)
So when you want to display events only on a certain day you have to extend this condition like:
(d.getDate() == dDay && (d.getMonth() - 1) == dMonth && d.getFullYear() == dYear)
dDay is a new varibale that holds the day that events should be held on.

Following your request within last answer to show "no events" when a month is selected and there are none available.
I have modified this plugin so that it shows a "text"(for instance "no events") when the list on the right side is empty. I have tested it and it works.
This modification is ok because it is MIT licensed.
(function($) {
var eCalendar = function(options, object) {
// Initializing global variables
var adDay = new Date().getDate();
var adMonth = new Date().getMonth();
var adYear = new Date().getFullYear();
var dDay = adDay;
var dMonth = adMonth;
var dYear = adYear;
var instance = object;
var settings = $.extend({}, $.fn.eCalendar.defaults, options);
function lpad(value, length, pad) {
if (typeof pad == 'undefined') {
pad = '0';
}
var p;
for (var i = 0; i < length; i++) {
p += pad;
}
return (p + value).slice(-length);
}
var mouseOver = function() {
$(this).addClass('c-nav-btn-over');
};
var mouseLeave = function() {
$(this).removeClass('c-nav-btn-over');
};
var mouseOverEvent = function() {
$(this).addClass('c-event-over');
var d = $(this).attr('data-event-day');
$('div.c-event-item[data-event-day="' + d + '"]').addClass('c-event-over');
};
var mouseLeaveEvent = function() {
$(this).removeClass('c-event-over')
var d = $(this).attr('data-event-day');
$('div.c-event-item[data-event-day="' + d + '"]').removeClass('c-event-over');
};
var mouseOverItem = function() {
$(this).addClass('c-event-over');
var d = $(this).attr('data-event-day');
$('div.c-event[data-event-day="' + d + '"]').addClass('c-event-over');
};
var mouseLeaveItem = function() {
$(this).removeClass('c-event-over')
var d = $(this).attr('data-event-day');
$('div.c-event[data-event-day="' + d + '"]').removeClass('c-event-over');
};
var nextMonth = function() {
if (dMonth < 11) {
dMonth++;
} else {
dMonth = 0;
dYear++;
}
print();
};
var previousMonth = function() {
if (dMonth > 0) {
dMonth--;
} else {
dMonth = 11;
dYear--;
}
print();
};
var checkEventsOnCurrentMonth = function() {
var eventNum = $('.c-event-list').find('.c-event-item') ? $('.c-event-list').find('.c-event-item').length : 0;
if (!eventNum) {
$('.c-event-list').html($.fn.eCalendar.defaults.noEventText);
}
};
function loadEvents() {
if (typeof settings.url != 'undefined' && settings.url != '') {
$.ajax({
url: settings.url,
async: false,
success: function(result) {
settings.events = result;
}
});
}
}
function print() {
loadEvents();
var dWeekDayOfMonthStart = new Date(dYear, dMonth, 1).getDay();
var dLastDayOfMonth = new Date(dYear, dMonth + 1, 0).getDate();
var dLastDayOfPreviousMonth = new Date(dYear, dMonth + 1, 0).getDate() - dWeekDayOfMonthStart + 1;
var cBody = $('<div/>').addClass('c-grid');
var cEvents = $('<div/>').addClass('c-event-grid');
var cEventsBody = $('<div/>').addClass('c-event-body');
cEvents.append($('<div/>').addClass('c-event-title c-pad-top').html(settings.eventTitle));
cEvents.append(cEventsBody);
var cNext = $('<div/>').addClass('c-next c-grid-title c-pad-top');
var cMonth = $('<div/>').addClass('c-month c-grid-title c-pad-top');
var cPrevious = $('<div/>').addClass('c-previous c-grid-title c-pad-top');
cPrevious.html(settings.textArrows.previous);
cMonth.html(settings.months[dMonth] + ' ' + dYear);
cNext.html(settings.textArrows.next);
cPrevious.on('mouseover', mouseOver).on('mouseleave', mouseLeave).on('click', previousMonth);
cNext.on('mouseover', mouseOver).on('mouseleave', mouseLeave).on('click', nextMonth);
cBody.append(cPrevious);
cBody.append(cMonth);
cBody.append(cNext);
for (var i = 0; i < settings.weekDays.length; i++) {
var cWeekDay = $('<div/>').addClass('c-week-day c-pad-top');
cWeekDay.html(settings.weekDays[i]);
cBody.append(cWeekDay);
}
var day = 1;
var dayOfNextMonth = 1;
for (var i = 0; i < 42; i++) {
var cDay = $('<div/>');
if (i < dWeekDayOfMonthStart) {
cDay.addClass('c-day-previous-month c-pad-top');
cDay.html(dLastDayOfPreviousMonth++);
} else if (day <= dLastDayOfMonth) {
cDay.addClass('c-day c-pad-top');
if (day == dDay && adMonth == dMonth && adYear == dYear) {
cDay.addClass('c-today');
}
for (var j = 0; j < settings.events.length; j++) {
var d = settings.events[j].datetime;
if (d.getDate() == day && (d.getMonth() - 1) == dMonth && d.getFullYear() == dYear) {
cDay.addClass('c-event').attr('data-event-day', d.getDate());
cDay.on('mouseover', mouseOverEvent).on('mouseleave', mouseLeaveEvent);
}
}
cDay.html(day++);
} else {
cDay.addClass('c-day-next-month c-pad-top');
cDay.html(dayOfNextMonth++);
}
cBody.append(cDay);
}
var eventList = $('<div/>').addClass('c-event-list');
for (var i = 0; i < settings.events.length; i++) {
var d = settings.events[i].datetime;
if ((d.getMonth() - 1) == dMonth && d.getFullYear() == dYear) {
var date = lpad(d.getDate(), 2) + '/' + lpad(d.getMonth(), 2) + ' ' + lpad(d.getHours(), 2) + ':' + lpad(d.getMinutes(), 2);
var item = $('<div/>').addClass('c-event-item');
var title = $('<div/>').addClass('title').html(date + ' ' + settings.events[i].title + '<br/>');
var description = $('<div/>').addClass('description').html(settings.events[i].description + '<br/>');
item.attr('data-event-day', d.getDate());
item.on('mouseover', mouseOverItem).on('mouseleave', mouseLeaveItem);
item.append(title).append(description);
eventList.append(item);
}
}
$(instance).addClass('calendar');
cEventsBody.append(eventList);
$(instance).html(cBody).append(cEvents);
checkEventsOnCurrentMonth();
}
return print();
}
$.fn.eCalendar = function(oInit) {
return this.each(function() {
return eCalendar(oInit, $(this));
});
};
// plugin defaults
$.fn.eCalendar.defaults = {
weekDays: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'],
textArrows: {
previous: '<',
next: '>'
},
eventTitle: 'Eventos',
noEventText: 'no events',
url: '',
events: [{
title: 'Brasil x Croácia',
description: 'Abertura da copa do mundo 2014',
datetime: new Date(2014, 6, 12, 17)
}, {
title: 'Brasil x México',
description: 'Segundo jogo da seleção brasileira',
datetime: new Date(2014, 6, 17, 16)
}, {
title: 'Brasil x Camarões',
description: 'Terceiro jogo da seleção brasileira',
datetime: new Date(2014, 6, 23, 16)
}]
};
}(jQuery));
.calendar * {
box-sizing: border-box;
font-family: Tahoma;
font-size: 14px;
}
.calendar-sm {
cursor: default;
width: 800px;
height: 370px;
}
.calendar {
cursor: default;
width: 600px;
height: 270px;
}
.calendar-sm .c-pad-top {
padding-top: 2%;
}
.calendar .c-pad-top {
padding-top: 3%;
}
.c-grid {
box-shadow: 2px 2px 5px #888888;
height: inherit;
}
.c-day {
width: 14.28%;
height: 13%;
background-color: #EFF4F9;
float: left;
text-align: center;
}
.c-day-previous-month {
width: 14.28%;
height: 13%;
background-color: #F9FBFD;
float: left;
text-align: center;
color: gray;
}
.c-day-next-month {
width: 14.28%;
height: 13%;
background-color: #F9FBFD;
float: left;
text-align: center;
color: gray;
}
.c-week-day {
width: 14.28%;
height: 10.38%;
background-color: rgb(145, 172, 203);
color: white;
float: left;
text-align: center;
font-weight: bold;
padding-top: 1%;
}
.c-next {
width: 12.5%;
height: 12%;
padding: 2% 2% 0 2%;
text-align: right;
cursor: pointer;
}
.c-previous {
width: 12.5%;
height: 12%;
padding: 2% 2% 0 2%;
text-align: left;
cursor: pointer;
}
.c-month {
width: 75%;
height: 12%;
text-align: center;
}
.c-nav-btn-over {
background-color: rgb(137, 163, 192) !important;
font-weight: bold;
}
.c-today {
background-color: #D8EAF1;
}
.c-event {
background-color: rgb(166, 166, 166);
color: white;
font-weight: bold;
cursor: pointer;
}
.c-grid {
float: left;
width: 50%;
}
.c-event-grid {
margin-left: 1px;
height: inherit;
width: 49%;
float: left;
box-shadow: 2px 2px 5px #888888;
}
.c-grid-title {
font-weight: bold;
float: left;
background-color: rgb(112, 145, 183);
color: white;
}
.c-event-title {
width: 100%;
height: 12%;
text-align: center;
font-weight: bold;
background-color: rgb(135, 155, 188);
color: white;
}
.c-event-body {
background-color: #EFF4F9;
height: 88.1%;
}
.c-event-list {
padding: 7 0 0 0;
overflow: auto;
height: 95%;
}
.c-event-item > .title {
font-weight: bold;
}
.c-event-item > div {
text-overflow: ellipsis;
width: inherit;
overflow: hidden;
white-space: nowrap;
}
.c-event-item {
padding-left: 10px;
margin-bottom: 10px;
}
.c-event-over {
background-color: lightgray;
font-weight: bold;
color: black;
}
.c-event-over > .description {
font-weight: normal;
}
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>jQuery e-calendar Plugin Demo</title>
<link href="http://www.jqueryscript.net/css/jquerysctipttop.css" rel="stylesheet" type="text/css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="../js/jquery.e-calendar.js"></script>
<script type="text/javascript" src="index.js"></script>
<link rel="stylesheet" href="../css/jquery.e-calendar.css" />
</head>
<body>
<div id="jquery-script-menu">
<div class="jquery-script-center">
<ul>
<li>Download This Plugin
</li>
<li>Back To jQueryScript.Net
</li>
</ul>
<div class="jquery-script-ads">
<script type="text/javascript">
<!--
google_ad_client = "ca-pub-2783044520727903";
/* jQuery_demo */
google_ad_slot = "2780937993";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<div class="jquery-script-clear"></div>
</div>
</div>
<h1 style="margin-top:150px;">jQuery e-calendar Plugin Demo</h1>
<div id="calendar"></div>
</body>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36251023-1']);
_gaq.push(['_setDomainName', 'jqueryscript.net']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
<script>
$(document).ready(function() {
$.fn.eCalendar.defaults.noEventText = '<br/>there are no events available';
$('#calendar').eCalendar({
weekDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
textArrows: {
previous: '<',
next: '>'
},
eventTitle: 'Events',
url: '',
events: [{
title: 'Event 1',
description: 'Description 1',
datetime: new Date(2014, 7, 15, 17)
}, {
title: 'Event 2',
description: 'Description 2',
datetime: new Date(2014, 7, 14, 16)
}, {
title: 'Event 3',
description: 'jQueryScript.Net',
datetime: new Date(2014, 7, 10, 16)
}]
});
});
</script>
</html>
This is the function that check whether the event-list is empty and show a text if it's true. Put this function after previousMonth-function or somewhere within the library:
var checkEventsOnCurrentMonth = function(){
var eventNum = $('.c-event-list').find('.c-event-item') ? $('.c-event-list').find('.c-event-item').length : 0;
if(!eventNum){
$('.c-event-list').html('no events');
}
};
This function you have to call at the end of print:
function print() {
...
...
...
$(instance).addClass('calendar');
cEventsBody.append(eventList);
$(instance).html(cBody).append(cEvents);
// this is the function you have to call at the end of print:
checkEventsOnCurrentMonth();
}
Furthermore you can define the text in another fashion.
There are default values or settings at the bottom of the library.
$.fn.eCalendar.defaults = {
weekDays: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'],
...
...
noEventText: 'no events',
...
...
};
I've defined a new property "noEventText" to be used as text when no events are available.
The function checkEventsOnCurrentMonth has to be altered for this new default-value(noEventText) to be taken into consideration:
var checkEventsOnCurrentMonth = function(){
var eventNum = $('.c-event-list').find('.c-event-item') ? $('.c-event-list').find('.c-event-item').length : 0;
if(!eventNum){
$('.c-event-list').html($.fn.eCalendar.defaults.noEventText);
}
};
At the end you can define the text before the plugin has been started:
$(document).ready(function () {
// here you can define the text and put some html into it.
$.fn.eCalendar.defaults.noEventText = 'there are no events available';
$('#calendar').eCalendar({
...
...
});
});
As mentioned I've tested it but only with the download-version you can find here: http://www.jqueryscript.net/time-clock/Create-A-Simple-Event-Calendar-with-jQuery-e-calendar.html
Image:

Related

Javascript and CSS code literally appearing on my HTML page

This is a simple calendar code. And my javascript and CSS codes are literally appearing beside my calendar. Does anyone know why something like this happens? I was using an online html/css/js editor and when I made my code into an HTML file, this happened. I've spent hours looking for a fault, but I can't find anything that is problematic.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ICSI301 - Lab 2</title>
</head>
<body>
<h1 id="year">2021 School Calendar</h1>
<div class="calendar">
</div>
</body>
</html>
<script>
var monthNamesRy = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var daysOfTheWeekRy = ["S", "M", "T", "W", "T", "F", "S"]
var d = new Date();
var year = d.getFullYear();
var thisMonth = d.getMonth();
var today = d.getDate();
//var nthday = d.getDay();
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
function createCalendar(month) {
var monthDiv = createMonthHeader(month);
var firstDayOfTheMonth = getFirstDayOfTheMonth(year, month);
var daysinmonth = daysInMonth(year, month)
var counter = 0, order = 6;
for (var i = 0; i < firstDayOfTheMonth + 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
for (var i = firstDayOfTheMonth; i < daysInMonth(year, month) + firstDayOfTheMonth; i++) {
counter++;
order++;
createDay(month, counter, order, monthDiv);
}
for (var i = firstDayOfTheMonth + daysinmonth; i < 6 * 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
}
function createDay(month, counter, order, monthDiv) {
var day = document.createElement("div");
if (month == thisMonth && counter == today) {
day.setAttribute("class", "to day");
} else {
day.setAttribute("class", "day");
}
day.setAttribute("style", "order:" + order);
day.innerHTML = counter;
monthDiv.appendChild(day);
}
function createMonthHeader(month) {
var calendar = document.querySelector(".calendar");
var monthDiv = document.createElement("div");
monthDiv.setAttribute("class", "month");
calendar.appendChild(monthDiv);
var h4 = document.createElement("h4");
h4.innerHTML = monthNamesRy[month];
monthDiv.appendChild(h4);
for (var i = 0; i < 7; i++) {
var hday = document.createElement("div");
hday.setAttribute("class", "day OfWeek");
hday.setAttribute("style", "order:" + i);
hday.innerHTML = daysOfTheWeekRy[i].toUpperCase();
monthDiv.appendChild(hday);
}
return monthDiv;
}
function daysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
function getMonthName(month) {
return monthNamesRy[month];
}
function getDayName(day) {
return daysOfTheWeekRy[day];
}
function getFirstDayOfTheMonth(y, m) {
var firstDay = new Date(y, m, 1);
return firstDay.getDay();
}
function getLastDayOfTheMonth(y, m) {
var lastDay = new Date(y, m + 1, 0);
return lastDay.getDay();
}
</script>
<style>
body * {
margin: 0;
padding: 0;
font-family: "Times New Roman";
}
.calendar, section {
max-width: 50rem;
}
.day {
width: 1.5em;
height: 1.5em;
}
.day:nth-of-type(-n+7) {
background-color: #7CFC00;
}
.to.day {
background: aquamarine;
}
.month {
width: calc(1.5em * 8);
padding: 1em;
}
h4 {
font-size: 1em;
text-transform: uppercase;
}
h1#year {
font-size: 3em;
height: 29px;
font-weight: normal;
padding: 1em 1em .5em 1em;
margin-bottom: .5em;
color: #006400;
}
body, body * {
display: flex;
justify-content: center;
}
h4 {
justify-content: center;
flex: 1 0 100%;
}
h1 {
justify-content: center;
align-self: stretch;
}
.calendar, .month {
flex-wrap: wrap;
}
.month {
align-items: flex-start;
border: 3px double black;
margin: 5px;
}
.day {
border: 1px solid black;
align-items: center;
justify-content: center;
}
</style>
Move the script and style to the head
change this
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
to
window.addEventListener("load",function() { // wait for page load
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
})
As Chris noticed, you have a very disruptive style entry
body,
body * {
display: flex;
justify-content: center;
}
I moved that to just under the other body style and now had to add
script,
style {
display: none
}
to stop the disruption
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ICSI301 - Lab 2</title>
<script>
var monthNamesRy = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var daysOfTheWeekRy = ["S", "M", "T", "W", "T", "F", "S"]
var d = new Date();
var year = d.getFullYear();
var thisMonth = d.getMonth();
var today = d.getDate();
//var nthday = d.getDay();
window.addEventListener("load", function() {
var daysOfTheMonthDiv = document.querySelectorAll(".daysOfTheMonth");
for (var month = 0; month < 12; month++) {
createCalendar(month);
}
});
function createCalendar(month) {
var monthDiv = createMonthHeader(month);
var firstDayOfTheMonth = getFirstDayOfTheMonth(year, month);
var daysinmonth = daysInMonth(year, month)
var counter = 0,
order = 6;
for (var i = 0; i < firstDayOfTheMonth + 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
for (var i = firstDayOfTheMonth; i < daysInMonth(year, month) + firstDayOfTheMonth; i++) {
counter++;
order++;
createDay(month, counter, order, monthDiv);
}
for (var i = firstDayOfTheMonth + daysinmonth; i < 6 * 7; i++) {
order++;
createDay(month, " ", order, monthDiv);
}
}
function createDay(month, counter, order, monthDiv) {
var day = document.createElement("div");
if (month == thisMonth && counter == today) {
day.setAttribute("class", "to day");
} else {
day.setAttribute("class", "day");
}
day.setAttribute("style", "order:" + order);
day.innerHTML = counter;
monthDiv.appendChild(day);
}
function createMonthHeader(month) {
var calendar = document.querySelector(".calendar");
var monthDiv = document.createElement("div");
monthDiv.setAttribute("class", "month");
calendar.appendChild(monthDiv);
var h4 = document.createElement("h4");
h4.innerHTML = monthNamesRy[month];
monthDiv.appendChild(h4);
for (var i = 0; i < 7; i++) {
var hday = document.createElement("div");
hday.setAttribute("class", "day OfWeek");
hday.setAttribute("style", "order:" + i);
hday.innerHTML = daysOfTheWeekRy[i].toUpperCase();
monthDiv.appendChild(hday);
}
return monthDiv;
}
function daysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
function getMonthName(month) {
return monthNamesRy[month];
}
function getDayName(day) {
return daysOfTheWeekRy[day];
}
function getFirstDayOfTheMonth(y, m) {
var firstDay = new Date(y, m, 1);
return firstDay.getDay();
}
function getLastDayOfTheMonth(y, m) {
var lastDay = new Date(y, m + 1, 0);
return lastDay.getDay();
}
</script>
<style>
body * {
margin: 0;
padding: 0;
font-family: "Times New Roman";
}
body,
body * {
display: flex;
justify-content: center;
}
script,
style {
display: none
}
.calendar,
section {
max-width: 50rem;
}
.day {
width: 1.5em;
height: 1.5em;
}
.day:nth-of-type(-n+7) {
background-color: #7CFC00;
}
.to.day {
background: aquamarine;
}
.month {
width: calc(1.5em * 8);
padding: 1em;
}
h4 {
font-size: 1em;
text-transform: uppercase;
}
h1#year {
font-size: 3em;
height: 29px;
font-weight: normal;
padding: 1em 1em .5em 1em;
margin-bottom: .5em;
color: #006400;
}
h4 {
justify-content: center;
flex: 1 0 100%;
}
h1 {
justify-content: center;
align-self: stretch;
}
.calendar,
.month {
flex-wrap: wrap;
}
.month {
align-items: flex-start;
border: 3px double black;
margin: 5px;
}
.day {
border: 1px solid black;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<h1 id="year">2021 School Calendar</h1>
<div class="calendar"></div>
</body>
</html>
This is more interesting than it seems at first. It's possible to solve the problem by moving the script to the head, but the content of script tags and style tags do not normally display in browsers. The reason they are displaying in this case is that the css is forcing the content of these tags to display.
The browser's css has
script {
display: none;
}
And this is overridden by these lines:
body, body * {
display: flex;
justify-content: center;
}
Browsers pull the invalidly-positioned tags into the body when building the DOM, and then apply this display attribute... which means the code runs, but it also shows on the page.
It can be fixed by moving the script tag, but that doesn't actually address the real cause of the problem

Javascript - Multiple File Uploader with Limit

This Javascript function allows for multiple file uploads and includes a file size limit, however it is missing a maximum number of files allowed to be uploaded.
The function handleFile(e) has the file type and size arguments passed through it but do not know where to introduce a limit on the allowable number of files to be uploaded.
const fInputs = document.querySelectorAll('.btcd-f-input>div>input')
function getFileSize(size) {
let _size = size
let unt = ['Bytes', 'KB', 'MB', 'GB'],
i = 0; while (_size > 900) { _size /= 1024; i++; }
return (Math.round(_size * 100) / 100) + ' ' + unt[i];
}
function delItem(el) {
fileList = { files: [] }
let fInp = el.parentNode.parentNode.parentNode.querySelector('input[type="file"]')
for (let i = 0; i < fInp.files.length; i++) {
fileList.files.push(fInp.files[i])
}
fileList.files.splice(el.getAttribute('data-index'), 1)
fInp.files = createFileList(...fileList.files)
if (fInp.files.length > 0) {
el.parentNode.parentNode.parentNode.querySelector('.btcd-f-title').innerHTML = `${fInp.files.length} File Selected`
} else {
el.parentNode.parentNode.parentNode.querySelector('.btcd-f-title').innerHTML = 'No File Chosen'
}
el.parentNode.remove()
}
function fade(element) {
let op = 1; // initial opacity
let timer = setInterval(function () {
if (op <= 0.1) {
clearInterval(timer);
element.style.display = 'none';
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op -= op * 0.1;
}, 50);
}
function unfade(element) {
let op = 0.01; // initial opacity
element.style.opacity = op;
element.style.display = 'flex';
let timer = setInterval(function () {
if (op >= 1) {
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 13);
}
function get_browser() {
let ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR|Edge\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: M[1]
};
}
for (let inp of fInputs) {
inp.parentNode.querySelector('.btcd-inpBtn>img').src = ''
inp.addEventListener('mousedown', function (e) { setPrevData(e) })
inp.addEventListener('change', function (e) { handleFile(e) })
}
let fileList = { files: [] }
let fName = null
let mxSiz = null
function setPrevData(e) {
if (e.target.hasAttribute('multiple') && fName !== e.target.name) {
console.log('multiple')
fName = e.target.name
fileList = fileList = { files: [] }
if (e.target.files.length > 0) {
for (let i = 0; i < e.target.files.length; i += 1) {
console.log(e.target.files[i])
fileList.files.push(e.target.files[i])
}
}
}
}
function handleFile(e) {
let err = []
const fLen = e.target.files.length;
mxSiz = e.target.parentNode.querySelector('.f-max')
mxSiz = mxSiz != null && (Number(mxSiz.innerHTML.replace(/\D/g, '')) * Math.pow(1024, 2))
if (e.target.hasAttribute('multiple')) {
for (let i = 0; i < fLen; i += 1) {
fileList.files.push(e.target.files[i])
}
} else {
fileList.files.push(e.target.files[0])
}
//type validate
if (e.target.hasAttribute('accept')) {
let tmpf = []
let type = new RegExp(e.target.getAttribute('accept').split(",").join("$|") + '$', 'gi')
for (let i = 0; i < fileList.files.length; i += 1) {
if (fileList.files[i].name.match(type)) {
tmpf.push(fileList.files[i])
} else {
err.push('Wrong File Type Selected')
}
}
fileList.files = tmpf
}
// size validate
if (mxSiz > 0) {
let tmpf = []
for (let i = 0; i < fileList.files.length; i += 1) {
if (fileList.files[i].size < mxSiz) {
tmpf.push(fileList.files[i])
mxSiz -= fileList.files[i].size
} else {
console.log('rejected', i, fileList.files[i].size)
err.push('Max Upload Size Exceeded')
}
}
fileList.files = tmpf
}
if (e.target.hasAttribute('multiple')) {
e.target.files = createFileList(...fileList.files)
} else {
e.target.files = createFileList(fileList.files[fileList.files.length - 1])
fileList = { files: [] }
}
// set File list view
if (e.target.files.length > 0) {
e.target.parentNode.querySelector('.btcd-f-title').innerHTML = e.target.files.length + ' File Selected'
e.target.parentNode.parentNode.querySelector('.btcd-files').innerHTML = ''
for (let i = 0; i < e.target.files.length; i += 1) {
let img = null
if (e.target.files[i].type.match(/image-*/)) {
img = window.URL.createObjectURL(e.target.files[i])
}
else {
img = ''
}
e.target.parentNode.parentNode.querySelector('.btcd-files').insertAdjacentHTML('beforeend', `<div>
<img src="${img}" alt="img" title="${e.target.files[i].name}">
<div>
<span title="${e.target.files[i].name}">${e.target.files[i].name}</span>
<br/>
<small>${getFileSize(e.target.files[i].size)}</small>
</div>
<button type="button" onclick="delItem(this)" data-index="${i}" title="Remove This File"><span>×</span></button>
</div>`)
}
}
// set eror
if (err.length > 0) {
for (let i = 0; i < err.length; i += 1) {
e.target.parentNode.parentNode.querySelector('.btcd-files').insertAdjacentHTML('afterbegin', `
<div style="background: #fff2f2;color: darkred;display:none" class="btcd-f-err">
<img src="" alt="img">
<span>${err[i]}</span>
</div>`)
}
const errNods = e.target.parentNode.parentNode.querySelectorAll('.btcd-files>.btcd-f-err')
for (let i = 0; i < errNods.length; i += 1) {
unfade(errNods[i])
setTimeout(() => { fade(errNods[i]) }, 3000);
setTimeout(() => { errNods[i].remove() }, 4000);
}
err = []
}
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
}
.btcd-f-input {
display: inline-block;
width: 340px;
position: relative;
overflow: hidden;
}
.btcd-f-input>div>input::-webkit-file-upload-button {
cursor: pointer;
}
.btcd-f-wrp {
cursor: pointer;
}
.btcd-f-wrp>small {
color: gray;
}
.btcd-f-wrp>button {
cursor: pointer;
background: #f3f3f3;
padding: 5px;
display: inline-block;
border-radius: 9px;
border: none;
margin-right: 8px;
height: 35px;
}
.btcd-f-wrp>button>img {
width: 24px;
}
.btcd-f-wrp>button>span,
.btcd-f-wrp>span,
.btcd-f-wrp>small {
vertical-align: super;
}
.btcd-f-input>.btcd-f-wrp>input {
z-index: 100;
width: 100%;
position: absolute;
opacity: 0;
left: 0;
height: 37px;
cursor: pointer;
}
.btcd-f-wrp:hover {
background: #fafafa;
border-radius: 10px;
}
.btcd-files>div {
display: flex;
align-items: center;
background: #f8f8f8;
border-radius: 10px;
margin-left: 30px;
width: 91%;
margin-top: 10px;
height: 40px;
}
.btcd-files>div>div {
display: inline-block;
width: 73%;
}
.btcd-files>div>div>small {
color: gray;
}
.btcd-files>div>img {
width: 40px;
height: 40px;
margin-right: 10px;
border-radius: 10px;
}
.btcd-files>div>div>span {
display: inline-block;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.btcd-files>div>button {
background: #e8e8e8;
border: none;
border-radius: 50px;
width: 25px;
height: 25px;
font-size: 20px;
margin-right: 6px;
padding: 0;
}
.btcd-files>div>button:hover {
background: #bbbbbb;
}
<div class="btcd-f-input">
<small>Multiple Upload</small>
<div class="btcd-f-wrp">
<button class="btcd-inpBtn" type="button"> <img src="" alt=""> <span> Attach File</span></button>
<span class="btcd-f-title">No File Chosen</span>
<small class="f-max">(Max 1 MB)</small>
<input multiple type="file" name="snd_multiple" id="">
</div>
<div class="btcd-files">
</div>
</div>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
<script src="https://unpkg.com/create-file-list#1.0.1/dist/create-file-list.min.js"></script>
In the function handleFile before type validate:
let maxFileNum = 10; // Maximum number of files
if (fileList.files.length > maxFileNum){
err.push("Too many files selected");
}

how to make date Auto Format in input textbox with javascript

when input yyyyMMdd format in textbox, that will automatically change to yyyy/MM/dd format for example: if your type 20180428, that will change to 2018/04/28
Utilizing built-in JavaScript functions such as parseInt to get the input element from a string to an integer, you are able to apply logic with helper functions to get to the date formatting you desire. e.g. if the day value is greater than 31, default return 1 instead to automatically guide the user from inputting a day more than 31
MDN JavaScript parseInt()
Afterwards, with the use of Regex, you can manipulate the user's initial data input (YYYYmmDD) to a format you want to change it to (YYYY/mm/DD).
Regex
I found an online tutorial outlining this very process below:
Auto-format Date Input by Envato Tuts+
var date = document.getElementById('date');
function checkValue(str, max) {
if (str.charAt(0) !== '0' || str == '00') {
var num = parseInt(str);
if (isNaN(num) || num <= 0 || num > max) num = 1;
str = num > parseInt(max.toString().charAt(0)) && num.toString().length == 1 ? '0' + num : num.toString();
};
return str;
};
date.addEventListener('input', function(e) {
this.type = 'text';
var input = this.value;
if (/\D\/$/.test(input)) input = input.substr(0, input.length - 3);
var values = input.split('/').map(function(v) {
return v.replace(/\D/g, '')
});
if (values[0]) values[0] = checkValue(values[0], 12);
if (values[1]) values[1] = checkValue(values[1], 31);
var output = values.map(function(v, i) {
return v.length == 2 && i < 2 ? v + ' / ' : v;
});
this.value = output.join('').substr(0, 14);
});
date.addEventListener('blur', function(e) {
this.type = 'text';
var input = this.value;
var values = input.split('/').map(function(v, i) {
return v.replace(/\D/g, '')
});
var output = '';
if (values.length == 3) {
var year = values[2].length !== 4 ? parseInt(values[2]) + 2000 : parseInt(values[2]);
var month = parseInt(values[0]) - 1;
var day = parseInt(values[1]);
var d = new Date(year, month, day);
if (!isNaN(d)) {
document.getElementById('result').innerText = d.toString();
var dates = [d.getMonth() + 1, d.getDate(), d.getFullYear()];
output = dates.map(function(v) {
v = v.toString();
return v.length == 1 ? '0' + v : v;
}).join(' / ');
};
};
this.value = output;
});
html {
box-sizing: border-box;
font-family: 'PT Sans', sans-serif;
-webkit-font-smoothing: antialiased;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
background-color: #f3f3f3;
}
form {
width: 100%;
max-width: 400px;
margin: 60px auto;
}
form input {
font-size: 30px;
padding: 0 20px;
border: 2px solid #ccc;
width: 100%;
color: #666;
line-height: 3;
border-radius: 7px;
font-family: 'PT Sans', sans-serif;
font-weight: bold;
}
form input:focus {
outline: 0;
}
form input.error {
border-color: #ff0000;
}
form label.error {
background-color: #ff0000;
color: #fff;
padding: 6px;
font-size: 11px;
}
label {
color: #999;
display: block;
margin-bottom: 10px;
text-transform: uppercase;
font-size: 18px;
font-weight: bold;
letter-spacing: 0.05em
}
form small {
color: #888;
font-size: 1em;
margin-top: 10px;
display: block;
align-self: ;
}
<form id="form" method="post" action="">
<label for="amount">Date</label>
<input type="text" id="date" />
<small>Enter date as Month / Day / Year</small>
</form>

Disable multiple checkboxes in dropdowns based on another selected checkbox of a first dropdown

Disable multiple checkboxes in dropdowns based on another selected checkbox of a first dropdown
I have multi-select 3 drop downs. All three dropdowns have same values. I want to disable second and third drop-down values based on the selected value of first. That means, when the user selected two options in first drop-down, the checkbox which contains those selected values in the first drop-down should get disabled in second drop-down and third drop-down and when user selected three options in second drop-down, the checkbox which contains those selected values in first drop-down, as well as second drop-down, should get disabled in third drop-down.
Priority is First drop-down than second and third respectively.
(function($) {
$.fn.fSelect = function(options) {
if ('string' === typeof options) {
var settings = options;
} else {
var settings = $.extend({
placeholder: 'Select some options',
numDisplayed: 3,
overflowText: '{n} selected',
searchText: 'Search',
showSearch: true,
optionFormatter: false
}, options);
}
/**
* Constructor
*/
function fSelect(select, settings) {
this.$select = $(select);
this.settings = settings;
this.create();
}
/**
* Prototype class
*/
fSelect.prototype = {
create: function() {
this.settings.multiple = this.$select.is('[multiple]');
var multiple = this.settings.multiple ? ' multiple' : '';
this.$select.wrap('<div class="fs-wrap' + multiple + '" tabindex="0" />');
this.$select.before('<div class="fs-label-wrap"><div class="fs-label">' + this.settings.placeholder + '</div><span class="fs-arrow"></span></div>');
this.$select.before('<div class="fs-dropdown hidden"><div class="fs-options"></div></div>');
this.$select.addClass('hidden');
this.$wrap = this.$select.closest('.fs-wrap');
this.$wrap.data('id', window.fSelect.num_items);
window.fSelect.num_items++;
this.reload();
},
reload: function() {
if (this.settings.showSearch) {
var search = '<div class="fs-search"><input type="search" placeholder="' + this.settings.searchText + '" /></div>';
this.$wrap.find('.fs-dropdown').prepend(search);
}
this.idx = 0;
this.optgroup = 0;
this.selected = [].concat(this.$select.val()); // force an array
var choices = this.buildOptions(this.$select);
this.$wrap.find('.fs-options').html(choices);
this.reloadDropdownLabel();
},
destroy: function() {
this.$wrap.find('.fs-label-wrap').remove();
this.$wrap.find('.fs-dropdown').remove();
this.$select.unwrap().removeClass('hidden');
},
buildOptions: function($element) {
var $this = this;
var choices = '';
$element.children().each(function(i, el) {
var $el = $(el);
if ('optgroup' == $el.prop('nodeName').toLowerCase()) {
choices += '<div class="fs-optgroup-label" data-group="' + $this.optgroup + '">' + $el.prop('label') + '</div>';
choices += $this.buildOptions($el);
$this.optgroup++;
} else {
var val = $el.prop('value');
// exclude the first option in multi-select mode
if (0 < $this.idx || '' != val || !$this.settings.multiple) {
var disabled = $el.is(':disabled') ? ' disabled' : '';
var selected = -1 < $.inArray(val, $this.selected) ? ' selected' : '';
var group = ' g' + $this.optgroup;
var row = '<div class="fs-option' + selected + disabled + group + '" data-value="' + val + '" data-index="' + $this.idx + '"><span class="fs-checkbox"><i></i></span><div class="fs-option-label">' + $el.html() + '</div></div>';
if ('function' === typeof $this.settings.optionFormatter) {
row = $this.settings.optionFormatter(row);
}
choices += row;
$this.idx++;
}
}
});
return choices;
},
reloadDropdownLabel: function() {
var settings = this.settings;
var labelText = [];
this.$wrap.find('.fs-option.selected').each(function(i, el) {
labelText.push($(el).find('.fs-option-label').text());
});
if (labelText.length < 1) {
labelText = settings.placeholder;
} else if (labelText.length > settings.numDisplayed) {
labelText = settings.overflowText.replace('{n}', labelText.length);
} else {
labelText = labelText.join(', ');
}
this.$wrap.find('.fs-label').html(labelText);
this.$wrap.toggleClass('fs-default', labelText === settings.placeholder);
this.$select.change();
}
}
/**
* Loop through each matching element
*/
return this.each(function() {
var data = $(this).data('fSelect');
if (!data) {
data = new fSelect(this, settings);
$(this).data('fSelect', data);
}
if ('string' === typeof settings) {
data[settings]();
}
});
}
/**
* Events
*/
window.fSelect = {
'num_items': 0,
'active_id': null,
'active_el': null,
'last_choice': null,
'idx': -1
};
$(document).on('click', '.fs-option:not(.hidden, .disabled)', function(e) {
var $wrap = $(this).closest('.fs-wrap');
var do_close = false;
if ($wrap.hasClass('multiple')) {
var selected = [];
// shift + click support
if (e.shiftKey && null != window.fSelect.last_choice) {
var current_choice = parseInt($(this).attr('data-index'));
var addOrRemove = !$(this).hasClass('selected');
var min = Math.min(window.fSelect.last_choice, current_choice);
var max = Math.max(window.fSelect.last_choice, current_choice);
for (i = min; i <= max; i++) {
$wrap.find('.fs-option[data-index=' + i + ']')
.not('.hidden, .disabled')
.each(function() {
$(this).toggleClass('selected', addOrRemove);
});
}
} else {
window.fSelect.last_choice = parseInt($(this).attr('data-index'));
$(this).toggleClass('selected');
}
$wrap.find('.fs-option.selected').each(function(i, el) {
selected.push($(el).attr('data-value'));
});
} else {
var selected = $(this).attr('data-value');
$wrap.find('.fs-option').removeClass('selected');
$(this).addClass('selected');
do_close = true;
}
$wrap.find('select').val(selected);
$wrap.find('select').fSelect('reloadDropdownLabel');
// fire an event
$(document).trigger('fs:changed', $wrap);
if (do_close) {
closeDropdown($wrap);
}
});
$(document).on('keyup', '.fs-search input', function(e) {
if (40 == e.which) { // down
$(this).blur();
return;
}
var $wrap = $(this).closest('.fs-wrap');
var matchOperators = /[|\\{}()[\]^$+*?.]/g;
var keywords = $(this).val().replace(matchOperators, '\\$&');
$wrap.find('.fs-option, .fs-optgroup-label').removeClass('hidden');
if ('' != keywords) {
$wrap.find('.fs-option').each(function() {
var regex = new RegExp(keywords, 'gi');
if (null === $(this).find('.fs-option-label').text().match(regex)) {
$(this).addClass('hidden');
}
});
$wrap.find('.fs-optgroup-label').each(function() {
var group = $(this).attr('data-group');
var num_visible = $(this).closest('.fs-options').find('.fs-option.g' + group + ':not(.hidden)').length;
if (num_visible < 1) {
$(this).addClass('hidden');
}
});
}
setIndexes($wrap);
});
$(document).on('click', function(e) {
var $el = $(e.target);
var $wrap = $el.closest('.fs-wrap');
if (0 < $wrap.length) {
// user clicked another fSelect box
if ($wrap.data('id') !== window.fSelect.active_id) {
closeDropdown();
}
// fSelect box was toggled
if ($el.hasClass('fs-label') || $el.hasClass('fs-arrow')) {
var is_hidden = $wrap.find('.fs-dropdown').hasClass('hidden');
if (is_hidden) {
openDropdown($wrap);
} else {
closeDropdown($wrap);
}
}
}
// clicked outside, close all fSelect boxes
else {
closeDropdown();
}
});
$(document).on('keydown', function(e) {
var $wrap = window.fSelect.active_el;
var $target = $(e.target);
// toggle the dropdown on space
if ($target.hasClass('fs-wrap')) {
if (32 == e.which) {
$target.find('.fs-label').trigger('click');
return;
}
}
// preserve spaces during search
else if (0 < $target.closest('.fs-search').length) {
if (32 == e.which) {
return;
}
} else if (null === $wrap) {
return;
}
if (38 == e.which) { // up
e.preventDefault();
$wrap.find('.fs-option.hl').removeClass('hl');
var $current = $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']');
var $prev = $current.prevAll('.fs-option:not(.hidden, .disabled)');
if ($prev.length > 0) {
window.fSelect.idx = parseInt($prev.attr('data-index'));
$wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']').addClass('hl');
setScroll($wrap);
} else {
window.fSelect.idx = -1;
$wrap.find('.fs-search input').focus();
}
} else if (40 == e.which) { // down
e.preventDefault();
var $current = $wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']');
if ($current.length < 1) {
var $next = $wrap.find('.fs-option:not(.hidden, .disabled):first');
} else {
var $next = $current.nextAll('.fs-option:not(.hidden, .disabled)');
}
if ($next.length > 0) {
window.fSelect.idx = parseInt($next.attr('data-index'));
$wrap.find('.fs-option.hl').removeClass('hl');
$wrap.find('.fs-option[data-index=' + window.fSelect.idx + ']').addClass('hl');
setScroll($wrap);
}
} else if (32 == e.which || 13 == e.which) { // space, enter
e.preventDefault();
$wrap.find('.fs-option.hl').click();
} else if (27 == e.which) { // esc
closeDropdown($wrap);
}
});
function setIndexes($wrap) {
$wrap.find('.fs-option.hl').removeClass('hl');
$wrap.find('.fs-search input').focus();
window.fSelect.idx = -1;
}
function setScroll($wrap) {
var $container = $wrap.find('.fs-options');
var $selected = $wrap.find('.fs-option.hl');
var itemMin = $selected.offset().top + $container.scrollTop();
var itemMax = itemMin + $selected.outerHeight();
var containerMin = $container.offset().top + $container.scrollTop();
var containerMax = containerMin + $container.outerHeight();
if (itemMax > containerMax) { // scroll down
var to = $container.scrollTop() + itemMax - containerMax;
$container.scrollTop(to);
} else if (itemMin < containerMin) { // scroll up
var to = $container.scrollTop() - containerMin - itemMin;
$container.scrollTop(to);
}
}
function openDropdown($wrap) {
window.fSelect.active_el = $wrap;
window.fSelect.active_id = $wrap.data('id');
window.fSelect.initial_values = $wrap.find('select').val();
$wrap.find('.fs-dropdown').removeClass('hidden');
$wrap.addClass('fs-open');
setIndexes($wrap);
}
function closeDropdown($wrap) {
if ('undefined' == typeof $wrap && null != window.fSelect.active_el) {
$wrap = window.fSelect.active_el;
}
if ('undefined' !== typeof $wrap) {
// only trigger if the values have changed
var initial_values = window.fSelect.initial_values;
var current_values = $wrap.find('select').val();
if (JSON.stringify(initial_values) != JSON.stringify(current_values)) {
$(document).trigger('fs:closed', $wrap);
}
}
$('.fs-wrap').removeClass('fs-open');
$('.fs-dropdown').addClass('hidden');
window.fSelect.active_el = null;
window.fSelect.active_id = null;
window.fSelect.last_choice = null;
}
})(jQuery);
.fs-wrap {
display: inline-block;
cursor: pointer;
line-height: 1;
width: 340px;
}
.fs-label-wrap {
position: relative;
background-color: #fff;
border: 1px solid #ddd;
cursor: default;
}
.fs-label-wrap,
.fs-dropdown {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fs-label-wrap .fs-label {
padding: 6px 22px 6px 8px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.fs-arrow {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #333;
position: absolute;
top: 0;
right: 5px;
bottom: 0;
margin: auto;
}
.fs-dropdown {
position: absolute;
background-color: #fff;
border: 1px solid #ddd;
width: 340px;
margin-top: 5px;
z-index: 1000;
}
.fs-dropdown .fs-options {
max-height: 200px;
overflow: auto;
}
.fs-search input {
border: none !important;
box-shadow: none !important;
outline: none;
padding: 4px 0;
width: 100%;
}
.fs-option,
.fs-search,
.fs-optgroup-label {
padding: 6px 8px;
border-bottom: 1px solid #eee;
cursor: default;
}
.fs-option:last-child {
border-bottom: none;
}
.fs-search {
padding: 0 4px;
}
.fs-option {
cursor: pointer;
}
.fs-option.disabled {
opacity: 0.4;
cursor: default;
}
.fs-option.hl {
background-color: #f5f5f5;
}
.fs-wrap.multiple .fs-option {
position: relative;
padding-left: 30px;
}
.fs-wrap.multiple .fs-checkbox {
position: absolute;
display: block;
width: 30px;
top: 0;
left: 0;
bottom: 0;
}
.fs-wrap.multiple .fs-option .fs-checkbox i {
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 14px;
height: 14px;
border: 1px solid #aeaeae;
border-radius: 2px;
background-color: #fff;
}
.fs-wrap.multiple .fs-option.selected .fs-checkbox i {
background-color: rgb(17, 169, 17);
border-color: transparent;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAGCAYAAAD+Bd/7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAABMSURBVAiZfc0xDkAAFIPhd2Kr1WRjcAExuIgzGUTIZ/AkImjSofnbNBAfHvzAHjOKNzhiQ42IDFXCDivaaxAJd0xYshT3QqBxqnxeHvhunpu23xnmAAAAAElFTkSuQmCC');
background-repeat: no-repeat;
background-position: center;
}
.fs-optgroup-label {
font-weight: bold;
text-align: center;
}
.hidden {
display: none;
}
<html>
<head>
<meta charset="UTF-8">
<title>Create Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://s.codepen.io/assets/libs/modernizr.js" type="text/javascript"></script>
<!-- The below url are required for dropdown -->
<link href="http://localhost/Performance/Test/css/fselect.css" rel="stylesheet">
<script src="http://localhost/Performance/Test/js/fSelect.js"></script>
<script>
(function($) {
$(function() {
$('#project_manager').fSelect();
$('#test_engineer').fSelect();
$('#viewer').fSelect();
});
})(jQuery);
</script>
</head>
<body>
<label>Select Project Manager :</label><br/>
<select id="project_manager" name="project_manager[]" multiple="multiple"><br/>
<optgroup label="pm">
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</optgroup>
</select><br/>
<label>Select Test Engineer :</label><br/>
<select id="test_engineer" name="test_engineer[]" multiple="multiple"><br/>
<optgroup label="te">
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</optgroup>
</select><br/>
<label>Select Viewer :</label><br/>
<select id="viewer" name="viewer[]" multiple="multiple"><br/>
<optgroup label="viewer">
<option value="1">Test 1</option>
<option value="2">Test 2</option>
<option value="3">Test 3</option>
</optgroup>
</select><br/>
</body>
</html>

Show count concatenated to labels using chart.js

I am using Chart.js to construct pie chart, is there any way to concatenate the Count to the label (Displaying numbers and percentages in a pie chart legend)?
createChart : function() {
debugger;
var chartData = [60, 90, 120, 150];
var chartLabels = ['apples','bananas','oranges','pears'];
var chartCanvas = component.find("chart").getElement();
var chart = new Chart(chartCanvas, {
type: 'pie',
data: {
labels: chartLabels,
datasets: [
{
label: "test",
data: chartData,
borderWidth: 0,
backgroundColor: [
"#f43004",
"#decf3f",
"#FFA500"
]
}
]
},
options: {
cutoutPercentage: 1,
maintainAspectRatio: false,
legend: {
display: true,
position:'right',
fullWidth:false,
reverse:true,
labels: {
fontColor: '#000',
fontSize:10,
fontFamily:"Arial, sans-serif SANS_SERIF"
},
layout: {
padding: 70,
}
}
}
});
}
I am trying to construct chart like this:
Please provide any suggestions or pointers to achieve this.
Thank you in advance.
You can use html-legends feature so you can customize the Chart.js legend:
legendCallback : function (chart) {
var text = [];
text.push('<ul class="0-legend">');
var ds = chart.data.datasets[0];
var sum = ds.data.reduce(function add(a, b) {
return a + b;
}, 0);
for (var i = 0; i < ds.data.length; i++) {
text.push('<li>');
var perc = Math.round(100 * ds.data[i] / sum, 0);
text.push('<span style="background-color:' + ds.backgroundColor[i] + '">' + '</span>' + chart.data.labels[i] + ' (' + ds.data[i] + ') (' + perc + '%)');
text.push('</li>');
}
text.push('</ul>');
return text.join("");
}
Here is a fiddle: https://jsfiddle.net/beaver71/b5hdn9gw/
var ctx = document.getElementById("myChart").getContext('2d');
var chartData = [60, 90, 120, 150];
var chartLabels = ['apples','bananas','oranges','pears'];
var chart = new Chart(ctx, {
type: 'pie',
data: {
labels: chartLabels,
datasets: [{
backgroundColor: [
"#f43004",
"#decf3f",
"#FFA500",
"#9b59b6",
],
data: chartData
}]
},
options: {
legend: {
display: false
},
legendCallback: function(chart) {
var text = [];
text.push('<ul class="0-legend">');
var ds = chart.data.datasets[0];
var sum = ds.data.reduce(function add(a, b) { return a + b; }, 0);
for (var i=0; i<ds.data.length; i++) {
text.push('<li>');
var perc = Math.round(100*ds.data[i]/sum,0);
text.push('<span style="background-color:' + ds.backgroundColor[i] + '">' + '</span>' + chart.data.labels[i] + ' ('+ds.data[i]+') ('+perc+'%)');
text.push('</li>');
}
text.push('</ul>');
return text.join("");
}
}
});
var myLegendContainer = document.getElementById("legend");
// generate HTML legend
myLegendContainer.innerHTML = chart.generateLegend();
// bind onClick event to all LI-tags of the legend
var legendItems = myLegendContainer.getElementsByTagName('li');
for (var i = 0; i < legendItems.length; i += 1) {
legendItems[i].addEventListener("click", legendClickCallback, false);
}
function legendClickCallback(event) {
event = event || window.event;
var target = event.target || event.srcElement;
while (target.nodeName !== 'LI') {
target = target.parentElement;
}
var parent = target.parentElement;
var chartId = parseInt(parent.classList[0].split("-")[0], 10);
var chart = Chart.instances[chartId];
var index = Array.prototype.slice.call(parent.children).indexOf(target);
var meta = chart.getDatasetMeta(0);
console.log(index);
var item = meta.data[index];
if (item.hidden === null || item.hidden === false) {
item.hidden = true;
target.classList.add('hidden');
} else {
target.classList.remove('hidden');
item.hidden = null;
}
chart.update();
}
body {
font-family: 'Arial';
}
.container {
margin: 15px auto;
}
#chart {
float: left;
width: 70%;
}
#legend {
float: right;
}
[class$="-legend"] {
list-style: none;
cursor: pointer;
padding-left: 0;
}
[class$="-legend"] li {
display: block;
padding: 0 5px;
}
[class$="-legend"] li.hidden {
text-decoration: line-through;
}
[class$="-legend"] li span {
border-radius: 5px;
display: inline-block;
height: 10px;
margin-right: 10px;
width: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<div class="container">
<h2>Chart.js — Pie Chart Demo Percent</h2>
<div>
<div id="chart"><canvas id="myChart"></canvas></div>
<div id="legend"></div>
</div>
</div>
var ctx = document.getElementById("myChart").getContext('2d');
var chartData = [60, 90, 120, 150];
var chartLabels = ['apples','bananas','oranges','pears'];
var chart = new Chart(ctx, {
type: 'pie',
data: {
labels: chartLabels,
datasets: [{
backgroundColor: [
"#f43004",
"#decf3f",
"#FFA500",
"#9b59b6",
],
data: chartData
}]
},
options: {
legend: {
display: false
},
legendCallback: function(chart) {
var text = [];
text.push('<ul class="0-legend">');
var ds = chart.data.datasets[0];
var sum = ds.data.reduce(function add(a, b) { return a + b; }, 0);
for (var i=0; i<ds.data.length; i++) {
text.push('<li>');
var perc = Math.round(100*ds.data[i]/sum,0);
text.push('<span style="background-color:' + ds.backgroundColor[i] + '">' + '</span>' + chart.data.labels[i] + ' ('+ds.data[i]+') ('+perc+'%)');
text.push('</li>');
}
text.push('</ul>');
return text.join("");
}
}
});
var myLegendContainer = document.getElementById("legend");
// generate HTML legend
myLegendContainer.innerHTML = chart.generateLegend();
// bind onClick event to all LI-tags of the legend
var legendItems = myLegendContainer.getElementsByTagName('li');
for (var i = 0; i < legendItems.length; i += 1) {
legendItems[i].addEventListener("click", legendClickCallback, false);
}
function legendClickCallback(event) {
event = event || window.event;
var target = event.target || event.srcElement;
while (target.nodeName !== 'LI') {
target = target.parentElement;
}
var parent = target.parentElement;
var chartId = parseInt(parent.classList[0].split("-")[0], 10);
var chart = Chart.instances[chartId];
var index = Array.prototype.slice.call(parent.children).indexOf(target);
var meta = chart.getDatasetMeta(0);
console.log(index);
var item = meta.data[index];
if (item.hidden === null || item.hidden === false) {
item.hidden = true;
target.classList.add('hidden');
} else {
target.classList.remove('hidden');
item.hidden = null;
}
chart.update();
}
body {
font-family: 'Arial';
}
.container {
margin: 15px auto;
}
#chart {
float: left;
width: 70%;
}
#legend {
float: right;
}
[class$="-legend"] {
list-style: none;
cursor: pointer;
padding-left: 0;
}
[class$="-legend"] li {
display: block;
padding: 0 5px;
}
[class$="-legend"] li.hidden {
text-decoration: line-through;
}
[class$="-legend"] li span {
border-radius: 5px;
display: inline-block;
height: 10px;
margin-right: 10px;
width: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<div class="container">
<h2>Chart.js — Pie Chart Demo Percent</h2>
<div>
<div id="chart"><canvas id="myChart"></canvas></div>
<div id="legend"></div>
</div>
</div>

Categories