سورس تقویم فارسی به همراه مناسبت ها با جاوا اسکریپت

سورس تقویم فارسی به همراه مناسبت ها با جاوا اسکریپت

سورس تقویم فارسی به همراه مناسبت – در این مقاله یک تقویم حرفه ای را خواهیم ساخت که قابلیت نمایش مناسبت ها علاوه بر شمسی ( میلادی و قمری ) ، تاریخ شمسی ، قمری ، میلادی ، نمایش روز های تعطیل ، ماه های عربی ، میلادی را خواهد داشت .

علاوه بر آن به 4 رنگ کلی برای تم تقویم با توجه به فصل فعلی که به طور خودکار عوض می شود .

دموی تقویم فارسی


فایل index.html

<!DOCTYPE html>
<html lang="fa">
<head>
  <meta charset="UTF-8">
  <title>Rapidcode.iR - سورس کد</title>
  <link rel="stylesheet" href="static/css/main.css">
</head>
<body>
  <div class="container">
    <a id="introduce" href="https://rapidcode.ir" target="_blank">رپید کد • کتابخانه مجازی برنامه نویسان</a>
    <div class="calendar-wrapper">
      <div class="calendar-base">

        <div class="year-wrapper">
        </div>

        <div class="months">
          <span class="month-hover month-letter month-letter-1" data-num="1">فروردین</span>
          <span class="month-hover month-letter month-letter-2" data-num="2">اردیبهشت</span>
          <span class="month-hover month-letter month-letter-3" data-num="3">خرداد</span>
          <span class="month-hover month-letter month-letter-4" data-num="4">تیر</span>
          <span class="month-hover month-letter month-letter-5" data-num="5">مرداد</span>
          <span class="month-hover month-letter month-letter-6" data-num="6">شهریور</span>
          <span class="month-hover month-letter month-letter-7" data-num="7">مهر</span>
          <span class="month-hover month-letter month-letter-8" data-num="8">آبان</span>
          <span class="month-hover month-letter month-letter-9" data-num="9">آذر</span>
          <span class="month-hover month-letter month-letter-10" data-num="10">دی</span>
          <span class="month-hover month-letter month-letter-11" data-num="11">بهمن</span>
          <span class="month-hover month-letter month-letter-12" data-num="12">اسفند</span>
        </div>
        <hr class="month-line" />

        <div class="days">
          <ul class="weeks">
            <li>شنبه</li>
            <li>یکشنبه</li>
            <li>دوشنبه</li>
            <li>سه شنبه</li>
            <li>چهارشنبه</li>
            <li>پنجشنبه</li>
            <li>جمعه</li>
            <div class="clearfix"></div>
          </ul>
        </div>

        <div class="num-dates"></div>

      </div>

      <div class="calendar-left active-season">

        <div class="num-date">X</div>
        <div class="day">X</div>

      </div>
    </div>
    <div class="clearfix"></div>

  </div>

  <script src="static/js/calendarObject.js"></script>
  <script src="static/js/app.js"></script>
</body>

</html>


main.css برای نمایش بهتر برنامه

.container{
    margin: 0 auto;
    width: 80%;
    text-align: center;
    direction: rtl;
}

#introduce{
    display: block;
    width: 100%;
    font-size: 35px;
    font-weight: bold;
    color: white;
    padding-bottom: 5px;
    background-color: #4CAF50;
    text-decoration: none;
    margin-bottom: 15px;
}


/* Page Style */

@font-face{font-family:Shabnam;src: url(../font/Shabnam.ttf) format("truetype");font-weight:400}

body {
  background-color: lightgray;
  font-family: 'Shabnam';
  margin: 0;
}

.dynamic-element{
	display: none;
}

.active-element{
	display: block;
}

.calendar-wrapper{
	text-align: left;
	direction: ltr;
	float: right;
}

.clearfix, .clearfix::before, .clearfix::after{
	clear: both;
	content: "";
	display:black;
}

.calendar-base {
  width: 900px;
  height: 570px;
  border-radius: 20px;
  background-color: white;
  position: relative;
  z-index: 1;
  color: black;
  overflow: hidden;
}

.active-season{
	background-color: #d3cccc !important;
	color:white !important;
}

.active-season-bg{
	background-color: #d3cccc !important;
}

.active-season-cr{
	color: #d3cccc !important;
}

.month-hover.active-season-cr{
	font-weight: bold;
}

.holiday{
	background-color: #f44336;
	color:#fff !important;
}

.holiday:hover{
	background-color: #d3cccc !important;
}

.disable-one{
	opacity: 0.3;
}

.year {
  color: #d3cccc;
  font-size: 30px;
  float: right;
  position: relative;
  right: 45px;
  top: 30px;
  font-weight: bold;
}

.year-meta{
	position: absolute;
	left: 335px;
	top: 25px;
	color: #d3cccc;
}

.triangle-left {
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-right: 10px solid #E8E8E8;
  border-bottom: 5px solid transparent;
  float: right;
  position: relative;
  right: 90px;
  top: 36px;
}

.triangle-right {
  width: 0;
  height: 0;
  border-top: 5px solid transparent;
  border-left: 10px solid #E8E8E8;
  border-bottom: 5px solid transparent;
  float: right;
  position: relative;
  left: 20px;
  top: 36px;
}
.triangle-left:hover{
  border-right: 10px solid#2ECC71;
}
.triangle-right:hover{
  border-left: 10px solid#2ECC71;
}

.month-color {
  color: #27AE60;
}
.month-hover:hover{
  cursor: pointer;
  color: #d3cccc !important;
}

.months {
  color: #6b6b6b;
  position: relative;
  left: 340px;
  top: 90px;
  word-spacing: 5px;
}

.month-line {
  border-color: #E8E8E8;
  position: relative;
  top: 85px;
  width: 57%;
  left: 178px;
}

.days {
  color: #6b6b6b;
  position: relative;
  font-size: 18px;
  left: 14px;
  top: 80px;
  word-spacing: 35px;
  font-weight: 600;
}

.days ul{
	margin: 0;
}

.days ul li{
  background-color: transparent !important;
  height: auto !important;
  word-spacing: -4px;
  font-size: 16px;
}

.num-dates {
   float: right;
   position: relative;
   top: 90px;
   right: 44px;
   z-index: 1;
}

.num-dates ul{
	margin: 0 0 20px 0;
	padding: 0;
}

.num-dates ul li, .days ul li{
	float: right;
    list-style: none;
    text-align: center;
    margin-left: 11px;
    width: 64px;
	font-weight: bold;
}

.num-dates ul li{
	padding: 10px 0;
	cursor: pointer;
	font-size: 22px;
	border-radius: 9px;
	position: relative;
	box-shadow: 0 0 35px #e5e3e3;
	color: #6b6b6b;
}

.num-dates ul li:hover{
	background-color: #d3cccc;
	color: white;
}

.num-dates ul li small{
	position: absolute;
	font-size: 12px;
    font-weight: normal;
	bottom: 2px;
}

.num-dates ul li small#miladi{
    right: 7px;
}

.num-dates ul li small#ghamari{
    left: 7px;
}

.active-day {
  width: 35px;
  height: 35px;
  border-radius: 50%;
  background-color: #2ECC71;
  position: relative;
  top: 295px;
  left: 661px;
}

.white {
  color: white;
}

.event-indicator {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background-color: #2980B9;
  position: relative;
  top: 304px;
  left: 695px;
}

.two {
  position: relative;
  top: 168px;
  left: 535px;
}

.grey {
  color: #AAAAB1;
}

.calendar-left {
  width: 300px;
  height: 570px;
  border-radius: 20px 0px 0px 20px;
  background-color: #2ECC71;
  position: relative;
  z-index: 1;
  bottom: 570px;
  color: white;
}

.hamburger {
  position: relative;
  top: 25px;
  left: 25px;
}

.burger-line:hover, .hamburger:hover{
  background-color:#27e879 !important;
}

.burger-line {
  width: 25px;
  height: 3px;
  background-color: white;
  border-radius: 15%;
  margin-bottom: 3px;
}

.num-date {
  font-size: 150px;
  width: 50%;
  margin: 0 auto;
  font-weight: 700;
  position: relative;
  top: -20px;
}

.day {
  width: 50%;
  margin: 0px auto;
  font-size: 30px;
  position: relative;
  bottom: 77px;
  text-align: center;
}

.current-events {
  font-size: 15px;
  position: relative;
  margin-left: 25px;
  bottom: 30px;
}

.posts {
  text-decoration: underline dotted;
}
.posts:hover{
  color:#27e879 !important;
}

.events-list{
	direction: rtl;
	float: right;
	position: relative;
    top: -83px;
    width: 93%;
	height: 377px;
    overflow-y: scroll;
    padding-right: 8px;
    text-align: right;
}

.events-list li{
	margin-bottom: 6px;
	font-size: 14px;
}

.events-list li span.event-day{
	font-weight: bold;
}

.events-list li div.event-title{
	display: inline-block;
	margin-left: 3px;
}


فایل app.js جهت کنترل بر رفتار برنامه

String.prototype.getBaseConversionNumber = getBaseConversionNumber
String.prototype.CvnFromTo = CvnFromTo;
String.prototype.convertDigits = convertDigits;

// تنظیم شده برای سال 1401
var today = Date.now();
const todayFa = {
	"day": getDateFormat(today, {
		"day": "2-digit"
	}),
	"month": getDateFormat(today, {
		"month": "numeric"
	}),
	"monthTitle": getDateFormat(today, {
		"month": "long"
	}),
	"year": getDateFormat(today, {
		"year": "numeric"
	}),
	"dayWeek": getDateFormat(today, {
		"weekday": "long"
	}),
}

const headDOM = document.getElementsByTagName("head")[0];

const parentDateDOM = document.getElementsByClassName('num-dates')[0];
const parentMetaYearDOM = document.getElementsByClassName('year-wrapper')[0];
const parentEventsDOM = document.getElementsByClassName('calendar-left')[0];

const todayDateDOM = document.getElementsByClassName("num-date")[0];
const todayDayDOM = document.getElementsByClassName("day")[0];

// set Property
todayDateDOM.textContent = todayFa['day'].convertDigits("fa");
todayDayDOM.textContent = todayFa['dayWeek'].convertDigits("fa");

// event listener
const monthLetter = document.getElementsByClassName("month-letter");
for (const element of monthLetter) {
	element.onclick = function (e) {
		const thisElement = e.target;
		if (thisElement.classList.contains("active-season-cr")) return;
		const monthDataNumber = thisElement.getAttribute("data-num");
		activeMonthElement('dynamic-element', `dynamic-element-${monthDataNumber}`, 'active-element');
		activeMonthElement('month-letter', `month-letter-${monthDataNumber}`, 'active-season-cr');

	}
}

let season = getSeasonByMonNum(todayFa.month);
let cssSeason = getCssBySeason(season);

let styleCustom = document.getElementById("style-cln");

if (!styleCustom)
	headDOM.innerHTML += `<style id="style-cln">${cssSeason}</style>`;
else {
	styleCustom.innerHTML = cssSeason;
}


let monthCounter = 1;
for (const month of calendarObject) {

	const dateList = [];
	let liCounter = 0;
	let UlCounter = 1;
	let oneStarted = false;
	let tmpMetaYear = metaYear.metaYear[monthCounter - 1];
	tmpMetaYear = tmpMetaYear.split(" | ");

	parentMetaYearDOM.innerHTML += generateTemplateHTML("metaYear", {
		index: monthCounter,
		year: metaYear.year,
		arabic: tmpMetaYear[1],
		miladi: tmpMetaYear[0],
	});

	for (const day of month) {
		const currentMonth = todayFa.monthTitle;
		if ((!dateList[0] && 9 < day[0]) || (dateList.indexOf(day[0]) != -1))
			oneStarted = false;
		else {
			oneStarted = true;
			dateList.push(day[0]);
		}
		var ulCurrentClass = `wk-${monthCounter}-${UlCounter}`;

		if (liCounter == 7) {
			document.getElementsByClassName(ulCurrentClass)[0].innerHTML += "<div class=\"clearfix\"></div>";
			liCounter = 0;
			UlCounter++;
		}

		ulCurrentClass = `wk-${monthCounter}-${UlCounter}`;

		var ulCurrent = document.getElementsByClassName(ulCurrentClass)[0];

		if (!ulCurrent) {
			var htmlUL = '';
			htmlUL += `<ul class="week ${ulCurrentClass} month-${monthCounter} dynamic-element dynamic-element-${monthCounter}"></ul>`;
			parentDateDOM.innerHTML += htmlUL;
			ulCurrent = document.getElementsByClassName(ulCurrentClass)[0];
		}
		let liClass = "day-element ";


		if (!oneStarted)
			liClass += "disable-one ";
		else if (oneStarted)
			liClass += `date-${monthCounter}-${day[0]} `;

		if (day[3] === true)
			liClass += "holiday ";

		ulCurrent.innerHTML += generateTemplateHTML('date', {
			class: liClass,
			jalali: day[0].toString().convertDigits("fa"),
			miladi: day[1],
			ghamari: day[2].toString().convertDigits("ar"),
		});

		const eventClass = `event-list-${monthCounter}`;
		let eventDOM = document.getElementsByClassName(eventClass)[0];
		if (!eventDOM) {
			parentEventsDOM.innerHTML += `<ul class="events-list event-list-${monthCounter} dynamic-element dynamic-element-${monthCounter}"></ul>`;
			eventDOM = document.getElementsByClassName(eventClass)[0];
		}

		for (const dayElement of day[4]) {
			const indexBracket = dayElement.indexOf("[");
			const eventdate = (0 <= indexBracket) ? dayElement.substring(indexBracket) : "";
			const eventTitle = dayElement.replace(eventdate, "");
			const startedDate = dateList[dateList.length - 1];

			if (oneStarted) {
				eventDOM.innerHTML += generateTemplateHTML('events', {
					day: `${startedDate} ${currentMonth}`.convertDigits("fa"),
					eventTitle: eventTitle,
					date: eventdate,
				});
			}
		}




		liCounter++;

	}

	monthCounter++;
}

activeMonthElement('dynamic-element', `dynamic-element-${todayFa.month}`, 'active-element');
activeMonthElement('month-letter', `month-letter-${todayFa.month}`, 'active-season-cr');
activeMonthElement('day-element', `date-${todayFa.month}-${parseInt(todayFa.day)}`, 'active-season');

function getSeasonByMonNum(numMonth) {
	const monthSeason = [
		"spring",
		"summer",
		"fall",
		"winter",
	];

	let season = "";

	if (numMonth <= 3) {
		season = monthSeason[0];
	} else if (3 < numMonth && numMonth <= 6) {
		season = monthSeason[1];
	} else if (6 < numMonth && numMonth <= 9) {
		season = monthSeason[2];
	} else if (9 < numMonth && numMonth <= 12) {
		season = monthSeason[3];
	}

	return season;
}

function getCssBySeason(season) {
	const cssObjects = cssProperty[season];
	let cssString = "";
	for (const cssObject of cssObjects) {
		let template = `${cssObject['selector']}{\n`;
		for (const property of cssObject['property']) {
			template += `${property}\n`;
		}
		template += "}\n\n"
		cssString += template;
	}

	return cssString;
}

function getDateFormat(uDate, option) {
	let date = new Intl.DateTimeFormat('fa-IR', option).format(uDate);
	date = date.convertDigits("en");
	return date;
}

function activeMonthElement(allCls, whichCls, activeCls) {
	const dynamicElement = document.getElementsByClassName(allCls);
	for (const element of dynamicElement) {
		if (element.classList.contains(activeCls))
			element.classList.remove(activeCls);
		else if (element.classList.contains(whichCls))
			element.classList.add(activeCls);
	}
}

function generateTemplateHTML(type, data) {
	let htmlTemplate = '';

	if (type == "date")
		htmlTemplate = `<li class="${data.class}"><span id="jalali">${data.jalali}</span><small id="miladi">${data.miladi}</small><small id="ghamari">${data.ghamari}</small></li>`;
	else if (type == "metaYear") {
		htmlTemplate = `<div class="year yr-${data.index} dynamic-element dynamic-element-${monthCounter}">${data.year}</div> <div class="year-meta myr-${data.index} dynamic-element dynamic-element-${monthCounter}">${data.arabic}<br>${data.miladi}</div>`;
	} else if (type == "events") {
		htmlTemplate = `<li><span class="event-day">${data.day} </span><div class="event-title">${data.eventTitle}</div><span class="event-date-type"> ${data.date}</span></li>`;
	}
	return htmlTemplate;
}

function convertDigits(to) {
	let str = this;
	const toCvn = (this.getBaseConversionNumber(to))[to];
	const allDigits = this.getBaseConversionNumber("all");

	delete allDigits[to];

	const Objkeys = Object.keys(allDigits);
	for (var i = 0; i < Objkeys.length; i++) {
		const currentKey = Objkeys[i];
		const fromCvn = allDigits[currentKey];
		str = this.CvnFromTo(fromCvn, toCvn, str)
	}
	return str;
}

function CvnFromTo(fromDigits, toDigits, str) {
	var str = str == undefined ? this : str;
	for (var i = 0; i < toDigits.length; i++) {
		const currentFromDigit = fromDigits[i];
		const currentToDigit = toDigits[i];
		const regex = new RegExp(currentFromDigit, 'g');
		str = str.replace(regex, currentToDigit);
	}
	return str;
}

function getBaseConversionNumber(label) {
	const faDigits = ['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'];
	const enDigits = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
	const arDigits = ['١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩', '٠'];

	var whichDigit = {};

	switch (label) {
		case 'fa':
			whichDigit[label] = faDigits;
			break;
		case 'en':
			whichDigit[label] = enDigits;
			break;
		case 'ar':
			whichDigit[label] = arDigits;
			break;
		case 'all':
			whichDigit = {
				"fa": faDigits,
				"en": enDigits,
				"ar": arDigits
			};
			break;
		default:
			whichDigit = [];
	}

	return whichDigit;
}

همچنین علاوه بر فایل های بالا فایل فونت و calendarObject.js هم نیز وجود دارد که داخل سورس قرار داده شده است که در پایین مقاله قابل دانلود است .

توجه داشته باشید calendarObject.js اطلاعات سال 1401 را دارد و قابلیت پویانمایی بر روی این سال دارد .

دانلود سورس تقویم فارسی به همراه مناسبت ها

ارسال نظر

جهت استفاده از کد حتما از تگ pre استفاده نمایید .

لیست نظرات

  1. سعید
    سعید

    سلام وقت بخیر چجوری میشه مناسبت سالهای آینده رو هم اضاف کرد؟ من میخوام روی وب سایتم تقویم شمسی مناسبتی داشته باشم که مناسبت هارو نشون میده. چیکار کنم سورس محدود به ۱۴۰۱ نباشه

    29 آبان 1401 | 07:37:40
  • حسین باقری
    حسین باقری

    درود ، برای این موضوع کافیه که ابتدا اطلاعات مثلا سال 1402 را از یک سایت به طور مرتب دریافت و به صورت الگویی که در calendarObject.js هست در بیارید البته با نام متفاوت مثل calendarObject1402 و سپس ضمیمه کنید و بعد از اون به javascript متصل کنید .
    البته در اسفند 1401 آموزشی مبنی بر همین سوال شما خواهم گذاشت .

    29 آبان 1401 | 11:01:32
  • مجتبی
    مجتبی

    سلام بر شما چجوری میشه این تقویم رو (بدون در نظر گرفتن مناسبت ها) برای هر سال نشون داد. مثلا یه لیست انتخابی از سال باشه که کاربر با انتخاب هر سال، بتونه تقویم اون سال رو ببینه(مناسبت ها مهم نیستن) ممنون میشم راهنمایی بفرمایید با تشکر

    18 مهر 1401 | 16:22:12
  • حامد
    حامد

    سلام خداقوت و تشکر امکان مرور سال های گذشته و آینده وجود داره؟ البته به مناسبت ها نیازی ندارم

    17 مرداد 1401 | 20:41:47
    • حسین باقری
      حسین باقری

      سلام ، بله در صورتی داده های سال های گذشته رو به پروژه اضافه کنید .

      21 مرداد 1401 | 14:22:35
  • سجاد
    سجاد

    سلام روزتون بخیر،امکانش هست بشه رویدادی به روزها اضافه کرد؟مثلا با کیلک کردن بروی تاریخ 26 خرداد بشه یه متنی به عنوان یاداوری نوشت

    28 خرداد 1401 | 10:33:58
    • حسین باقری
      حسین باقری

      سلام بله امکان پذیر هست .

      28 خرداد 1401 | 13:07:45
  • محمد
    محمد

    سلام خسته نباشی امکان کوچیک کردن کلی تقویم رو داره؟

    09 خرداد 1401 | 23:44:03
    • حسین باقری
      حسین باقری

      سلام ، بله از استایل زیر می تونید استفاده کنید . در فایل main.css

      .calendar-wrapper{ transform: scale(0.5); }

      10 خرداد 1401 | 10:58:14
  • امیر
    امیر

    با سلام تقویم فقط سال ۱۴۰۱ رو داره ؟ امسال رو ندارد ؟

    17 بهمن 1400 | 18:56:59
    • حسین باقری
      حسین باقری

      امسال که رو به پایانه و سال جدید 1401 وجود داره .

      20 بهمن 1400 | 15:52:41
    contact us