Website of the International Forum «Electric Networks»  Visit site

  • HTML5
  • CSS3
  • JavaScript
  • Modx

Turnkey development of the forum «Electric Networks» site: design, page layout, integration with cms MODx and site publication.

Web site development

Completed works

  1. Design: creation in Photoshop, drawing graphics, backgrounds and icons.
  2. Layout implemented adaptive page layout (Html, Css, pure JavaScript).
  3. Integration with cms MODx. creating sections and pages, 6 templates (Main, News, Empty, Page, Page with text, Photo gallery), using MIGX for slideshow carousels.

JS libraries used

Implemented on the site

  1. preloader, sticky header;
  2. forum member registration form in a modal window;
  3. on the main page: background YouTube video in the first screen, carousel slider (Photo Gallery section) using splide.js, countdown counter (Invitation section);
  4. internal pages: design of texts, photos, lists and quotes, on the Contacts page - Yandex map with VDNKh pavilions;
  5. cookie message panel;
  6. photo galleries: using lightgallery.js (https://expoelectroseti.ru/fotogalereya/2022), image slider in pure Css when hovering over a separate album (https://expoelectroseti.ru/fotogalereya);
  7. animation of elements when scrolling the page, hover effects;
  8. service pages (Consent to data processing, Privacy policy) and error pages;
  • Home page
  • Inner page
  • News list
  • News page
  • Photogallery
  • Contact
  • Popup form
Layout of the main page of the corporate website
Internal page of the corporate website
Web design of news cards
Blog page design
Layout of the photogallery
Contact page design
Popup registration form

View all folders and files

Here below is just the script file:

script.js
										// Cookies message
function getCookie(name) {
	let matches = document.cookie.match(new RegExp(
    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
	));
	return matches ? decodeURIComponent(matches[1]) : undefined;
}

let cookiecook = getCookie("cookiecook"),
    cookiewin = document.getElementsByClassName('cookie_notice')[0];

if (cookiecook != "no") {
	cookiewin.style.display="block";
	document.getElementById("cookie_close").addEventListener("click", function(){
		cookiewin.style.display="none";
		let date = new Date;
		date.setDate(date.getDate() + 1);
		document.cookie = "cookiecook=no; path=/; expires=" + date.toUTCString();
	});
}

(function() {
	const homePage = document.querySelector('.home-page');

  function replaceAll(string, search, replace) {
    return string.split(search).join(replace);
  }

  // Sticky header
  var prevScrollpos = window.pageYOffset,
      header = document.getElementById("header");

  window.onscroll = function() {

    var currentScrollpos = window.pageYOffset;

    if (prevScrollpos > currentScrollpos) {
      header.style.top = "0";
      header.classList.add('sticky');
    } else if (currentScrollpos < 30) {
      header.style.top = "0";
    } else {
      header.style.top = "-120px";
    }

    prevScrollpos = currentScrollpos;

    if (currentScrollpos < 30) header.classList.remove('sticky');
  }

  // Menu links format
  let menuLinks = document.querySelectorAll('.menu_list a');
  menuLinks.forEach(function (link) {
    let linkText = '';
    if (link.innerHTML.indexOf(' ') !== -1) {
      let spaceIndex = link.innerHTML.indexOf(' ');
      linkText = '<span>' + link.innerHTML.slice(0, spaceIndex) + ' </span>' + link.innerHTML.slice(spaceIndex + 1);
    } else {
      linkText = '<span>' + link.innerHTML + ' </span>';
    }
    link.innerHTML = linkText;
  });

  // Mobile menu
  let menuIcon = document.querySelector('.menu_icon'),
      widthWindow = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

  if (widthWindow <= 991) {
    let menuOverlay = document.querySelector('.menu_overlay');

    menuIcon.addEventListener('click', function () {
      menuIcon.closest('.menu').classList.toggle('open');
      document.body.classList.toggle("noscroll");
    });

    menuOverlay.addEventListener('click', function () {
      menuIcon.closest('.menu').classList.remove('open');
      document.body.classList.remove("noscroll");
    });
  }

  // Hero - Sponsors list format
  const sponsors = document.querySelector('.hero_content__sponsorlist');

	if (homePage !== null) {
		let heroHeight = 0,
				widthIntroVideo = 0,
				heroHeightIncrement = widthWindow > 991 ? 280 : 180;

	  if (sponsors !== null) {
	    let sponsorsText = replaceAll(sponsors.innerHTML, ',', '</span><span>');
	    sponsors.innerHTML = sponsorsText;
	  }

		function setHeightIntroVideo() {
			const heroContentText = document.querySelector('.hero_content__text'),
						heroContentBoundary = heroContentText.getBoundingClientRect(),
						heroContentHeight = Math.trunc(heroContentBoundary.height) + heroHeightIncrement;
			document.querySelector('.hero').style.height = heroContentHeight + 'px';
			heroHeight = heroContentHeight + 20;
			widthIntroVideo = 16 * heroHeight / 9;
		}
		setHeightIntroVideo();

		window.addEventListener('resize', function(event) {
	    setHeightIntroVideo();

			let youtubeEmbed = document.getElementById("youtubeEmbed");
			youtubeEmbed.style.height = heroHeight + 'px';
			youtubeEmbed.style.width = widthIntroVideo + 'px';
		}, true);

		// Intro - video background
	  var youtubeEmbedElement = document.getElementById("youtubeEmbed");

	  // Add YouTube API script
	  if (widthWindow > 991) {
	    var tag = document.createElement("script");
	    tag.src = "https://www.youtube.com/iframe_api";
	    var firstScriptTag = document.getElementsByTagName("script")[0];
	    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

	    var player;
	    var videoId = youtubeEmbedElement.dataset.videoId;
	    var startSeconds = 2;
	    var endSeconds = youtubeEmbedElement.getAttribute('data-video-time');

	    onYouTubeIframeAPIReady = function () {
	      player = new YT.Player("youtubeEmbed", {
	        videoId: videoId, // YouTube Video ID
	        playerVars: {
	          autoplay: 1, // Auto-play the video on load
	          autohide: 1, // Hide video controls when playing
	          disablekb: 1,
	          controls: 0, // Hide pause/play buttons in player
	          showinfo: 0, // Hide the video title
	          modestbranding: 1, // Hide the Youtube Logo
	          loop: 1, // Run the video in a loop
	          fs: 0, // Hide the full screen button
	          rel: 0,
	          enablejsapi: 1,
	          start: startSeconds,
	          end: endSeconds
	        },
	        events: {
	          onReady: function (e) {
	            e.target.mute();
	            e.target.playVideo();
	          },
	          onStateChange: function (e) {
	            if (e.data === YT.PlayerState.PLAYING) {
					let youtubeEmbed = document.getElementById("youtubeEmbed");
	              youtubeEmbed.classList.add("loaded");
					youtubeEmbed.style.height = heroHeight + 'px';
					youtubeEmbed.style.width = widthIntroVideo + 'px';
	            }

	            if (e.data === YT.PlayerState.ENDED) {
	              // Loop from starting point
	              player.seekTo(startSeconds);
	            }
	          }
	        }
	      });
	    };
	  }

		new Splide( '#homegallery', {
		  	type   : 'loop',
		  	perPage: 2,
		    breakpoints: {
		  		991: {
		  			perPage: 1,
		  		}
		  	},
		  	perMove: 1,
		    pagination: false
		  } ).mount();
	}

  // Countdown timer on the Home page
  const daysVal = document.querySelector('.time-count__days .time-count__val');
  if (homePage !== null) {

    document.addEventListener('DOMContentLoaded', () => {

			const forumStart = daysVal.getAttribute('data-forumstart') + 'T00:00';
			const targetData = new Date(forumStart);
    	const hoursVal = document.querySelector('.time-count__hours .time-count__val');
    	const minutesVal = document.querySelector('.time-count__minutes .time-count__val');

    	const daysText = document.querySelector('.time-count__days .time-count__text');
    	const hoursText = document.querySelector('.time-count__hours .time-count__text');
    	const minutesText = document.querySelector('.time-count__minutes .time-count__text');

    	function declOfNum(number, titles) {
    		let cases = [2, 0, 1, 1, 1, 2];
    		return titles[ (number%100>4 && number%100<20)? 2 : cases[(number%10<5)?number%10:5] ];
    	}

    	const timeCount = () => {
    		let now = new Date();
    		let leftUntil = targetData - now;

				if (leftUntil <= 0) daysVal.closest('.invitation').classList.add('forumcoming');

    		let days = Math.floor(leftUntil / 1000 / 60 / 60 / 24);
    		let hours = Math.floor(leftUntil / 1000 / 60 / 60) % 24;
    		let minutes = Math.floor(leftUntil / 1000 / 60) % 60;

    		daysVal.textContent = days;
    		hoursVal.textContent =	hours;
    		minutesVal.textContent = minutes;

    		daysText.textContent = declOfNum(days, ['день', 'дня', 'дней']);
    		hoursText.textContent = declOfNum(hours, ['час', 'часа', 'часов']);
    		minutesText.textContent = declOfNum(minutes, ['минута', 'минуты', 'минут']);
    	};

    	timeCount();
    	setInterval(timeCount, 1000);
    });
  }

  // Show Scroll-to-top button
  const scrollToTopButton = document.getElementById('js-top');
  const toggleScrollToTopBtn = function() {
    let y = window.scrollY;
    if (y > 0) {
      scrollToTopButton.className = "top-link show";
    } else {
      scrollToTopButton.className = "top-link hide";
    }
  };
	scrollToTopButton.onclick = function(e) {
    e.preventDefault();
    window.scrollTo(pageXOffset, 0);
  }
  window.addEventListener("scroll", toggleScrollToTopBtn);

  // Preloader
  const loaderEl = document.getElementsByClassName('fullpage-loader')[0];

  function hidePreloader(event) {
    // const readyState = "interactive";
  	const readyState = "complete";

  	if(document.readyState == readyState) {
  		// when document ready add lass to fadeout loader
  		loaderEl.classList.add('fullpage-loader--invisible');

  		// when loader is invisible remove it from the DOM
  		setTimeout( () => {
  			loaderEl.parentNode.removeChild(loaderEl);
  		}, 2000)
    }
  }

  document.addEventListener('readystatechange', hidePreloader);

	// POP-UP Window
	const modalTriggers = document.querySelectorAll('.popup-trigger'),
	      modalCloseTrigger = document.querySelector('.popup-modal__close'),
	      bodyBlackout = document.querySelector('.body-blackout'),
				bodyTag = document.querySelector('body');

	modalTriggers.forEach(trigger => {
	  trigger.addEventListener('click', (event) => {
	    event.preventDefault();
	    const { popupTrigger } = trigger.dataset;
	    const popupModal = document.querySelector(`[data-popup-modal="${popupTrigger}"]`);

	    popupModal.classList.add('is--visible');
	    bodyBlackout.classList.add('is-blacked-out');
	    bodyTag.classList.add('noscroll');
			header.classList.remove('transition');

	    popupModal.querySelector('.popup-modal__close').addEventListener('click', () => {
	      closeModal();
	    });

	    bodyBlackout.addEventListener('click', () => {
	      closeModal();
	    });

			function closeModal() {
				popupModal.classList.remove('is--visible');
				bodyBlackout.classList.remove('is-blacked-out');
				bodyTag.classList.remove('noscroll');
				setTimeout(function () {
					header.classList.add('transition');
				}, 500);
			}
	  });
	});

	// Registration Form
  const registrForm = document.querySelector('#registrForm'),
		registrAgreement = document.getElementById('registrAgreement'),
	  registrMessages = document.querySelectorAll('.registr-message')[0];
		// registrTestForm = document.querySelector('#registrTestForm'); // https://expoelectroseti.ru/test-dev/

	registrAgreement.onchange = function() {
		registrAgreement.parentNode.classList.remove('error-checkbox');
	};
	if (registrForm !== null) registrForm.addEventListener('submit', sendFormRegistr);
	// if (registrTestForm !== null) registrTestForm.addEventListener('submit', sendTestFormRegistr);
	async function sendFormRegistr(e) {
		e.preventDefault();

	  const registrName = document.getElementById('registrName'),
	      registrOrg = document.getElementById('registrOrg'),
			  registrPos = document.getElementById('registrPos'),
				registrAddr = document.getElementById('registrAddr'),
			  registrPhone = document.getElementById('registrPhone'),
	      registrEmail = document.getElementById('registrEmail'),
	      registrFields = [registrName, registrOrg, registrPos, registrAddr, registrPhone, registrEmail];
	  let formValid = true;

	  registrFields.forEach( (field, index) => {
	    field.classList.remove('error');
	    formValid = true;

			if (field.value === '' || index === registrFields.length - 1 && field.value.indexOf('@') === -1) {
	      field.classList.add('error');
	      formValid = false;
	    }
	  });

		if (!registrAgreement.checked) {
			registrAgreement.parentNode.classList.add('error-checkbox');
			formValid = false;
		}

		if (formValid) {
			let response = await fetch('https://expoelectroseti.ru/assets/templates/electro/mail.php', {
				method: 'post',
				headers: {
					'Content-Type': 'application/json;charset=utf-8'
				},
				body: JSON.stringify({
					registrName: registrName.value,
					registrOrg: registrOrg.value,
					registrPos: registrPos.value,
					registrAddr: registrAddr.value,
					registrPhone: registrPhone.value,
					registrEmail: registrEmail.value
				})
			});

			let resultForm = await response.json();
			registrMessages.innerHTML = resultForm.message;

			registrName.value = '';
			registrOrg.value = '';
			registrPos.value = '';
			registrAddr.value = '';
			registrPhone.value = '';
			registrEmail.value = '';
			registrAgreement.checked = false;

		} else {
			registrMessages.innerHTML = "<span style='color:red;'>Заполните все поля!</span>";
		}
	}

	// Photo Gallery
	const photoGallery = document.getElementById('lightgallery');
	if (photoGallery !== null) {

		let photoGalleryCode = '',
				srcLargeImageArr = [];
		const imagesPhotoGallery = photoGallery.querySelectorAll('img');
		imagesPhotoGallery.forEach(function (img) {
			const srcImagePhotoGallery = img.getAttribute('src'),
						srcLargeImagePhotoGallery = replaceAll(srcImagePhotoGallery, '-mini', ''),
						altImagePhotoGallery = img.getAttribute('alt');
			srcLargeImageArr.push(srcLargeImagePhotoGallery);
			photoGalleryCode += `<a href="${srcLargeImagePhotoGallery}" data-sub-html="${altImagePhotoGallery}">
	        <img src="${srcImagePhotoGallery}">
	    </a>`
		});

		photoGallery.innerHTML = photoGalleryCode;

		lightGallery(document.getElementById('lightgallery'));

		setTimeout(function () {
			document.querySelectorAll('#lightgallery img').forEach(function (img, index) {
				img.setAttribute('src', srcLargeImageArr[index])
			});
		}, 4000);
	}
	// Gallery albums page
	const photogalleryListImages = document.querySelectorAll('.photogallery-list__images');
	if (photogalleryListImages !== null) {

		photogalleryListImages.forEach(function (images) {
			let imagesCode = '',
					imagesInside = images.querySelectorAll('img'),
					imagesInsideSrcArr = [];
			imagesInside.forEach(function (img) {
				if (img.getAttribute('src').length) imagesInsideSrcArr.push(img.getAttribute('src'));
			});
			imagesInsideSrcArr.forEach(function (src, index) {
				if (index < 6) imagesCode += `<img src="${src}">`;
				if (index === 6) imagesCode += `<img src="${imagesInsideSrcArr[0]}">`;
			});
			images.innerHTML = imagesCode;
		});
	}

	// IMAGE ZOOM
  function scaleImage(image) {
    image.addEventListener('click', function () {
      var srcImg = image.getAttribute('src');
      srcImg = srcImg.replace("-small", "");
      addPopupImg(srcImg);
      document.querySelector('.imgzoom__close').addEventListener("click", function () {
        removePopupImg();
      });
      document.querySelector('.imgzoom__overlay').addEventListener("click", function () {
        removePopupImg();
      });
    });
  }
  function addPopupImg(srcImg) {
    var popupImg = document.createElement('div');
    popupImg.className = 'imgzoom__popup';
    document.body.prepend(popupImg);

    var overlay = document.createElement('div');
    overlay.className = 'imgzoom__overlay';
    popupImg.append(overlay);

    var imgLarge = document.createElement('img');
    imgLarge.setAttribute("src",srcImg);
    popupImg.append(imgLarge);

    var btnClose = document.createElement('div');
    btnClose.className = 'imgzoom__close';
    btnClose.innerHTML = "×";
    popupImg.append(btnClose);
  }
  function removePopupImg() {
    document.body.removeChild(document.querySelector('.imgzoom__popup'));
  }
  var imgsZoomable = document.querySelectorAll('.imgzoom');
  imgsZoomable.forEach(function (img) {
		img.setAttribute('title', img.getAttribute('alt'));
    scaleImage(img);
  });

	// Animations
	const animatedElements = document.querySelectorAll('[data-animation], section.content h2'),
				contentSection = document.querySelector('section.content');
	let isScrolling = false;

	if (contentSection !== null && document.querySelector('.home-page') === null) {
		const contentCaptions = contentSection.querySelectorAll('h2');
		contentCaptions.forEach(function (caption, index) {
			if (index !== 0) caption.setAttribute('data-animation', 'showFromBottom');
		});
	}

  window.addEventListener("scroll", throttleScroll, false);

	function throttleScroll(e) {
	  if (isScrolling == false) {
			window.requestAnimationFrame(function() {
	      scrolling(e);
	      isScrolling = false;
	    });
	  }
	  isScrolling = true;
	}

	function scrolling(e) {
	  animatedElements.forEach((elem) => {
	    if (isFullyVisible(elem)) elem.classList.add('animated', elem.getAttribute('data-animation'));
	    if (isPartiallyVisible(elem)) {
	      elem.classList.add('animated', elem.getAttribute('data-animation'));
	    } else {
	      elem.classList.remove('animated', elem.getAttribute('data-animation'));
	    }
	  })
	}

	function isPartiallyVisible(el) {
	  const elementBoundary = el.getBoundingClientRect(),
	        top = elementBoundary.top,
	        bottom = elementBoundary.bottom,
	        height = elementBoundary.height;
	  return ((top + height / 2 >= 0) && (height + window.innerHeight >= bottom + 80));
	}

	function isFullyVisible(el) {
	  const elementBoundary = el.getBoundingClientRect(),
	        top = elementBoundary.top,
	        bottom = elementBoundary.bottom;

	  return ((top >= 0) && (bottom + 80 <= window.innerHeight));
	}

}());
									
Back to top