script.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. $(document).ready( () => {
  2. lazyLoading()
  3. displayPictograms()
  4. getDeviceSize()
  5. hideMobileNavOnResize()
  6. hoverDesktopNavItems()
  7. if (currentPage.text().trim() == 'Accueil') {
  8. hideFooter()
  9. animateText()
  10. } else if (currentPage.text().trim() == 'Projets' && $('main').children(":first").attr('id') != 'reader') {
  11. hideFooter()
  12. loadProjetIndex()
  13. } else if ($('main').children(":first").attr('id') == 'reader') {
  14. hideFooter()
  15. displayReader()
  16. }
  17. initBarba()
  18. })
  19. // GLOBAL VARIABLES
  20. let isMobileNavOpen = false,
  21. isDesktopDevice = false,
  22. currentPage,
  23. indexIsReady = false,
  24. filterObj = {
  25. publiqueCardsDisplayed : true,
  26. socialeCardsDisplayed : true,
  27. culturelleCardsDisplayed : true
  28. },
  29. projectTitleIsScrolling = false,
  30. titleScrollTimer
  31. // MAIN FUNCTIONS
  32. function initBarba() {
  33. barba.init({
  34. prefetchIgnore: true,
  35. transitions: [{
  36. name: 'opacity-transition',
  37. leave(data) {
  38. return gsap.to(data.current.container, {
  39. opacity: 0
  40. })
  41. },
  42. enter(data) {
  43. return gsap.from(data.next.container, {
  44. opacity: 0
  45. })
  46. }
  47. }]
  48. })
  49. barba.hooks.beforeLeave((data) => {
  50. if (isMobileNavOpen) { toggleMobileNav() }
  51. if ($(data.current.container).attr('id') == 'projets-index') { resetFilters() }
  52. if ($(data.current.container).attr('id') == 'text-content' ) { hideFooter() }
  53. })
  54. barba.hooks.afterLeave((data) => {
  55. if ($(data.current.container).attr('id') == 'reader') {
  56. if ($(data.next.container).attr('id') != 'reader') {
  57. leaveReader()
  58. $('#nav-container h1').empty().append(currentPage.text())
  59. }
  60. }
  61. })
  62. barba.hooks.beforeEnter((data) => {
  63. lazyLoading()
  64. displayPictograms()
  65. $('html, body').scrollTop(0)
  66. if ($(data.next.container).attr('id') == 'index-content') {
  67. animateText()
  68. indexIsReady = false
  69. } else if ($(data.next.container).attr('id') == 'projets-index') {
  70. loadProjetIndex()
  71. filterWhenEntering()
  72. } else if ($(data.next.container).attr('id') == 'text-content')
  73. { if (isDesktopDevice) { displayFooter() } }
  74. })
  75. barba.hooks.after((data) => {
  76. let pageTitleComparator, navIndex
  77. switch ($('main').children(":first").attr('id')) {
  78. case 'index-content':
  79. pageTitleComparator = 'Accueil'
  80. navIndex = 0
  81. break
  82. case 'text-content':
  83. // dirty hack to get what content it is
  84. if ($('main').children(":first").children(":first").text().substring(3).replace(/ .*/,'') == "équipe") {
  85. pageTitleComparator = 'Le collectif'
  86. navIndex = 1;
  87. } else {
  88. pageTitleComparator = 'Logiciels Libres'
  89. navIndex = 3;
  90. }
  91. break
  92. case 'projets-index':
  93. case 'reader':
  94. pageTitleComparator = 'Projets'
  95. navIndex = 2
  96. break
  97. }
  98. if (pageTitleComparator != currentPage.text().trim()) {
  99. changeMenuSelected($('header nav ul li').eq(navIndex))
  100. }
  101. if ($(data.next.container).attr('id') == 'reader') {
  102. displayReader()
  103. }
  104. })
  105. }
  106. function lazyLoading() {
  107. $('.lazy').Lazy({
  108. scrollDirection: 'vertical',
  109. effect: 'fadeIn',
  110. effectTime: 400,
  111. threshold: 100,
  112. afterLoad: function(element) {
  113. $(element).removeClass('loader')
  114. if ($(element).parent().is('figure')) {
  115. $(element).parent().addClass('loaded')
  116. } else {
  117. $(element).parentsUntil('figure').parent().addClass('loaded')
  118. }
  119. }
  120. })
  121. }
  122. // UI FUNCTIONS
  123. // general content
  124. function displayPictograms() {
  125. // To be able to change the pictograms color through scss variables
  126. addLinkPictogram()
  127. $('.picto').each((i, el) => {
  128. let source = $(el).data('src')
  129. $(el).css({
  130. '-webkit-mask': 'url(' + source + ') 0% 0% / contain no-repeat',
  131. 'mask': 'url(' + source + ') 0% 0% / contain no-repeat',
  132. })
  133. })
  134. }
  135. function addLinkPictogram() {
  136. $('main a[target="_blank"]').each( (i, e) => {
  137. $(e).append('<div class="picto picto-url" data-src="/user/themes/figureslibres-v2/images/pictos/arrow-diagonal.svg" aria-hidden="true"></div>')
  138. })
  139. // hardcoded url because cant use twig in js
  140. }
  141. function getDeviceSize() {
  142. function setDeviceSize() {
  143. if (window.matchMedia('(min-width: 996px)').matches) {
  144. isDesktopDevice = true
  145. } else {
  146. isDesktopDevice = false
  147. }
  148. }
  149. setDeviceSize()
  150. let timer
  151. $(window).on('resize', () => {
  152. clearTimeout(timer)
  153. timer = setTimeout(setDeviceSize(), 100)
  154. refreshUiOnResize()
  155. })
  156. }
  157. function refreshUiOnResize() {
  158. hideFooterOnResize()
  159. hideMobileNavOnResize()
  160. checkTitleAutoScroll()
  161. }
  162. function triggerLazyLoading() {
  163. setTimeout(() => {
  164. $(document).scrollTop($(document).scrollTop() + 1)
  165. setTimeout(() => {
  166. $(document).scrollTop($(document).scrollTop() - 1)
  167. }, 100)
  168. }, 300)
  169. }
  170. function titleScrollTop() {
  171. if ($('html, body').scrollTop() > 0) {
  172. $('html, body').animate({scrollTop: 0}, 1200)
  173. if (currentPage.text().trim() == 'Accueil') {
  174. toggleIndexContent(true)
  175. }
  176. }
  177. }
  178. // set navigation
  179. function toggleMobileNav() {
  180. if (!isMobileNavOpen) {
  181. $('nav').addClass('mobile-nav-open')
  182. $('footer').fadeIn()
  183. isMobileNavOpen = true
  184. } else {
  185. $('nav').removeClass('mobile-nav-open')
  186. isMobileNavOpen = false
  187. if (window.matchMedia('(min-width: 576px)').matches && (currentPage.text().trim() == 'Figures Libres' || currentPage.text().trim() == 'Logiciels Libres')) {
  188. return
  189. } else {
  190. $('footer').fadeOut()
  191. }
  192. }
  193. }
  194. function hideMobileNavOnResize() {
  195. if (!isDesktopDevice) {
  196. if (isMobileNavOpen) {
  197. toggleMobileNav()
  198. }
  199. $('nav').css('display', 'none')
  200. setTimeout( () => {
  201. $('nav').css('display', 'flex')
  202. }, 200)
  203. }
  204. }
  205. function hoverDesktopNavItems() {
  206. currentPage = $('.selected')
  207. $('nav li').hover(() => {
  208. if (isDesktopDevice) {
  209. currentPage.removeClass('selected')
  210. }
  211. }, () => {
  212. if (isDesktopDevice) {
  213. currentPage.addClass('selected')
  214. }
  215. })
  216. }
  217. function changeMenuSelected(page) {
  218. $('.selected').removeClass('selected')
  219. currentPage = $(page)
  220. currentPage.addClass('selected')
  221. changeMobileTitle()
  222. }
  223. function changeMobileTitle() {
  224. $('#nav-container h1').empty().append(currentPage.text())
  225. }
  226. // index interaction
  227. function toggleIndexContent(closeEverything) {
  228. let isTextOpen = false,
  229. isCommanditairesOpen = false,
  230. isExtraitOpen = false,
  231. quelExtrait
  232. if (closeEverything) {
  233. closeEverything()
  234. }
  235. $('#second-p-index, #commanditaires-grid, #extrait-publique, #extrait-social, #extrait-culturelle').children().fadeOut()
  236. $('#arrowIndex').click( () => {
  237. if (!isTextOpen && !isExtraitOpen) {
  238. if (isDesktopDevice) {
  239. displayContent($('#second-p-index'), '70vh')
  240. } else {
  241. displayContent($('#second-p-index'), '90vh')
  242. }
  243. turnArrow('down')
  244. isTextOpen = true
  245. } else {
  246. if (isExtraitOpen) {
  247. hideContent($('#extrait-' + quelExtrait))
  248. $('#' + quelExtrait).css('text-decoration', 'none')
  249. isExtraitOpen = false
  250. turnArrow('top')
  251. }
  252. if (isTextOpen) {
  253. hideContent($('#second-p-index'))
  254. turnArrow('top')
  255. isTextOpen = false
  256. }
  257. if (isCommanditairesOpen) {
  258. hideContent($('#commanditaires-grid'))
  259. $('#commanditaires').css('text-decoration', 'none')
  260. isCommanditairesOpen = false
  261. }
  262. }
  263. })
  264. $('#index-content canvas').click( function(event) {
  265. target = $(event.target).parent().attr('id')
  266. if (target == 'publique' || target == 'sociale' || target == 'culturelle') {
  267. toggleExtrait(target)
  268. return false
  269. } else if (target == 'commanditaires') {
  270. toggleCommanditaires()
  271. return false
  272. } else {
  273. switch (target) {
  274. case 'figureslibres':
  275. changeMenuSelected($('nav li a[href$=collectif]').parent())
  276. break
  277. case 'logicielslibres':
  278. changeMenuSelected($('nav li a[href$=logiciels-libres]').parent())
  279. break
  280. case 'projets':
  281. changeMenuSelected($('nav li a[href$=projets]').parent())
  282. break
  283. }
  284. }
  285. })
  286. $('#extrait-projets .projets-link-filter').click(() => {
  287. changeMenuSelected($('nav li a[href$=projets]').parent())
  288. })
  289. function toggleExtrait(category) {
  290. if(!isExtraitOpen) {
  291. if (isTextOpen) {
  292. hideContent($('#second-p-index'))
  293. isTextOpen = false
  294. }
  295. if (isCommanditairesOpen) {
  296. hideContent($('#commanditaires-grid'))
  297. $('#commanditaires').css('text-decoration', 'none')
  298. isCommanditairesOpen = false
  299. }
  300. displayContent($('#extrait-' + category), '80vh')
  301. turnArrow('down')
  302. $('#' + category).css({'text-decoration': 'underline', 'text-decoration-thickness': '2px', 'text-underline-offset': '8px'})
  303. isExtraitOpen = true
  304. quelExtrait = category
  305. } else if (isExtraitOpen && quelExtrait != category) {
  306. hideContent($('#extrait-' + quelExtrait))
  307. $('#' + category).css({'text-decoration': 'underline', 'text-decoration-thickness': '2px', 'text-underline-offset': '8px'})
  308. $('#' + quelExtrait).css('text-decoration', 'none')
  309. setTimeout(() => {
  310. displayContent($('#extrait-' + category), '80vh')
  311. quelExtrait = category
  312. }, 1000)
  313. } else if (isExtraitOpen && quelExtrait == category) {
  314. hideContent($('#extrait-' + category))
  315. turnArrow('top')
  316. $('#' + category).css('text-decoration', 'none')
  317. isExtraitOpen = false
  318. }
  319. }
  320. function toggleCommanditaires() {
  321. if (!isCommanditairesOpen) {
  322. displayContent($('#commanditaires-grid'), '150vh')
  323. $('#commanditaires').css({'text-decoration': 'underline', 'text-decoration-thickness': '2px', 'text-underline-offset': '8px'})
  324. isCommanditairesOpen = true
  325. } else {
  326. hideContent($('#commanditaires-grid'))
  327. $('#commanditaires').css('text-decoration', 'none')
  328. isCommanditairesOpen = false
  329. }
  330. }
  331. function closeEverything() {
  332. if (isTextOpen) {
  333. hideContent($('#second-p-index'))
  334. isTextOpen = false
  335. }
  336. if (isExtraitOpen) {
  337. hideContent($('#extrait-' + quelExtrait))
  338. $('#' + quelExtrait).css('text-decoration', 'none')
  339. isExtraitOpen = false
  340. }
  341. if (isCommanditairesOpen) {
  342. hideContent($('#commanditaires-grid'))
  343. $('#commanditaires').css('text-decoration', 'none')
  344. isCommanditairesOpen = false
  345. }
  346. turnArrow('top')
  347. }
  348. }
  349. function turnArrow(direction) {
  350. if (direction == 'down') {
  351. $('#arrow-container').css({
  352. 'transform': 'rotate(180deg)',
  353. 'margin-bottom': '10vh'
  354. })
  355. $('#arrow-container .picto').removeAttr('id')
  356. } else if (direction == 'top') {
  357. $('#arrow-container').css({
  358. 'transform': 'rotate(0deg)',
  359. 'margin-bottom': '0vh'
  360. })
  361. $('#arrow-container .picto').attr('id', 'arrowIndex')
  362. }
  363. }
  364. function displayContent(content, maxHeight) {
  365. content.children().fadeIn()
  366. setTimeout( () => {
  367. content.css({
  368. 'max-height': maxHeight,
  369. 'opacity': '1'
  370. })
  371. if (isDesktopDevice) {
  372. content.css('margin-top', '3vh')
  373. }
  374. }, 200)
  375. setTimeout( () => {
  376. $('html, body').animate({
  377. scrollTop: $(content).position().top
  378. }, 1200, 'swing')
  379. }, 400)
  380. }
  381. function hideContent(content) {
  382. content.css({
  383. 'max-height': '0vh',
  384. 'opacity': '0',
  385. 'margin-top': '0vh'
  386. })
  387. setTimeout(() => {
  388. content.children().fadeOut()
  389. }, 1200)
  390. }
  391. // index animation
  392. function animateText() {
  393. waitForWebfonts(['Moche'], () => { // idk why listing only one font makes it work....
  394. // For each item
  395. $(".animateText").each(function(i, e) {
  396. $(e).contents().wrap('<span></span>')
  397. $('#main-p-index span').css('color', 'transparent')
  398. $('#second-p-index span').css('color', 'transparent')
  399. // Initialize a new LiquidText instance
  400. var liquidText = new LiquidText(
  401. e, // Element
  402. 0.0, // Liquid Volatility
  403. 0.5 // Speed
  404. ).start()
  405. })
  406. toggleIndexContent()
  407. displayIndexWhenReady()
  408. })
  409. }
  410. let globalMaterial = new Blotter.LiquidDistortMaterial()
  411. let globalBlotter = new Blotter(globalMaterial, {
  412. texts: [],
  413. autostart: false,
  414. autobuild: false
  415. })
  416. class LiquidText {
  417. constructor(element, volatility, speed) {
  418. this.element = element
  419. this.text = element.text
  420. this.fontSize = parseInt($(element).css('font-size'))
  421. this.fontStack = $(element).css('font-family')
  422. this.fontWeight = $(element).css('font-weight')
  423. this.fontColor = $(element).css('color')
  424. this.material = globalMaterial
  425. this.hoverDuration = 0.35
  426. this.hoverEase = Linear.easeIn
  427. this.liquidVolatility = volatility
  428. this.liquidSpeed = speed
  429. this.scope = null
  430. this.blotter = globalBlotter
  431. this.blotterText = null
  432. this.onResize = this.onResize.bind(this)
  433. this.seed = 0.1
  434. window.addEventListener('resize', this.onResize)
  435. this.initialize()
  436. }
  437. initialize() {
  438. let blotter = this.blotter
  439. let text = new Blotter.Text(this.text, {
  440. family: this.fontStack,
  441. size: this.fontSize,
  442. fill: this.fontColor,
  443. weight: this.fontWeight,
  444. paddingLeft: 15,
  445. paddingRight: 15
  446. })
  447. this.blotterText = text
  448. this.material.uniforms.uSpeed.value = this.liquidSpeed
  449. this.material.uniforms.uVolatility.value = this.liquidVolatility
  450. blotter.addText(text)
  451. blotter.needsUpdate = true
  452. var scope = blotter.forText(text)
  453. this.scope = scope
  454. scope.appendTo(this.element)
  455. this.material.needsUpdate = true
  456. gsap.fromTo(this.material.uniforms.uVolatility, this.hoverDuration, {
  457. value: 0,
  458. ease: this.hoverEase
  459. }, {
  460. value: this.liquidVolatility,
  461. ease: this.hoverEase
  462. })
  463. this.element.onmouseenter = (event) => {
  464. this.scope.material.needsUpdate = true
  465. gsap.fromTo(this.scope.material.uniforms.uVolatility, this.hoverDuration, {
  466. value: 0,
  467. ease: this.hoverEase
  468. }, {
  469. value: this.liquidVolatility + 0.04,
  470. ease: this.hoverEase
  471. })
  472. }
  473. this.element.onmouseleave = (event) => {
  474. gsap.fromTo(this.scope.material.uniforms.uVolatility, this.hoverDuration, {
  475. value: this.scope.material.uniforms.uVolatility.value,
  476. ease: this.hoverEase
  477. }, {
  478. value: this.liquidVolatility,
  479. ease: this.hoverEase,
  480. onComplete: () => {
  481. this.scope.material.needsUpdate = true
  482. }
  483. })
  484. }
  485. }
  486. stop() {
  487. this.blotter.stop()
  488. }
  489. start() {
  490. this.blotter.start()
  491. }
  492. onResize() {
  493. let text = this.blotterText
  494. let time = 100
  495. let timer
  496. if(timer) clearTimeout(timer)
  497. timer = setTimeout(() => {
  498. text.properties.size = parseInt($(this.element).css('font-size'))
  499. text.needsUpdate = true
  500. }, time, event)
  501. }
  502. }
  503. function displayIndexWhenReady() {
  504. globalBlotter.on('update', () => {
  505. if (!indexIsReady) {
  506. indexIsReady = true
  507. $('#loader-index').fadeOut(1400)
  508. }
  509. })
  510. }
  511. function waitForWebfonts(fonts, callback) {
  512. var loadedFonts = 0
  513. for (var i = 0, l = fonts.length; i < l; ++i) {
  514. ((font) => {
  515. var node = document.createElement('span')
  516. // Characters that vary significantly among different fonts
  517. node.innerHTML = 'giItT1WQy@!-/#'
  518. // Visible - so we can measure it - but not on the screen
  519. node.style.position = 'absolute'
  520. node.style.left = '-10000px'
  521. node.style.top = '-10000px'
  522. // Large font size makes even subtle changes obvious
  523. node.style.fontSize = '300px'
  524. // Reset any font properties
  525. node.style.fontFamily = 'sans-serif'
  526. node.style.fontVariant = 'normal'
  527. node.style.fontStyle = 'normal'
  528. node.style.fontWeight = 'normal'
  529. node.style.letterSpacing = '0'
  530. document.body.appendChild(node)
  531. // Remember width with no applied web font
  532. var width = node.offsetWidth
  533. node.style.fontFamily = font + ', sans-serif'
  534. var interval
  535. function checkFont() {
  536. // Compare current width with original width
  537. if (node && node.offsetWidth != width) {
  538. ++loadedFonts
  539. node.parentNode.removeChild(node)
  540. node = null
  541. }
  542. // If all fonts have been loaded
  543. if (loadedFonts >= fonts.length) {
  544. if (interval) {
  545. clearInterval(interval)
  546. }
  547. if (loadedFonts == fonts.length) {
  548. callback()
  549. return true
  550. }
  551. }
  552. }
  553. if (!checkFont()) {
  554. interval = setInterval(checkFont, 50)
  555. }
  556. })(fonts[i])
  557. }
  558. }
  559. // display project grid
  560. function toggleCategory(category) {
  561. let chevron = $(category).find('.chevron-category')
  562. if (chevron.hasClass('close')) {
  563. $(chevron.removeClass('close'))
  564. $(category).next().slideToggle('slow')
  565. $('.card-displayed figure').each(function() {
  566. if ($(this).css('transform') != 'none') {
  567. $(this).css('transform', 'none')
  568. }
  569. })
  570. } else {
  571. $(chevron.addClass('close'))
  572. $(category).next().slideToggle('slow')
  573. triggerLazyLoading()
  574. }
  575. }
  576. function filterCards(utilite) {
  577. let filterIsOn
  578. function checkFilter() {
  579. switch (utilite) {
  580. case 'publique':
  581. filterIsOn = filterObj.publiqueCardsDisplayed ? true : false
  582. if (filterObj.publiqueCardsDisplayed) {
  583. filterObj.publiqueCardsDisplayed = false
  584. } else {
  585. filterObj.publiqueCardsDisplayed = true
  586. }
  587. break
  588. case 'sociale':
  589. filterIsOn = filterObj.socialeCardsDisplayed ? true : false
  590. if (filterObj.socialeCardsDisplayed) {
  591. filterObj.socialeCardsDisplayed = false
  592. } else {
  593. filterObj.socialeCardsDisplayed = true
  594. }
  595. break
  596. case 'culturelle':
  597. filterIsOn = filterObj.culturelleCardsDisplayed ? true : false
  598. if (filterObj.culturelleCardsDisplayed) {
  599. filterObj.culturelleCardsDisplayed = false
  600. } else {
  601. filterObj.culturelleCardsDisplayed = true
  602. }
  603. break
  604. }
  605. }
  606. if (Object.values(filterObj).every(Boolean) || Object.values(filterObj).every(e => e == false)) { // si tous les filtres sont actifs (état de base)
  607. $('.projets-grid div').each(function () { // hide all cards
  608. if($(this).hasClass(utilite + '-card')) { // except those from the filtered category
  609. $(this).removeClass('card-hidden').addClass('card-displayed')
  610. }
  611. else {
  612. $(this).removeClass('card-displayed').addClass('card-hidden')
  613. }
  614. })
  615. $('#' + utilite + '-filter').css('opacity', 1)
  616. Object.keys(filterObj).forEach(v => filterObj[v] = false)
  617. checkFilter()
  618. }
  619. else if (Object.values(filterObj).filter(Boolean).length == 1) {
  620. // check if the filter is on or off
  621. checkFilter()
  622. if (filterIsOn) {
  623. $('#' + utilite + '-filter').css('opacity', 0.4)
  624. $('.projets-grid div').each(function () { // display all cards
  625. $(this).removeClass('card-hidden').addClass('card-displayed')
  626. })
  627. } else {
  628. $('#' + utilite + '-filter').css('opacity', 1)
  629. $('.' + utilite + '-card').each(function () { // only display cards from selected category
  630. $(this).removeClass('card-hidden').addClass('card-displayed')
  631. })
  632. }
  633. }
  634. else if (Object.values(filterObj).filter(Boolean).length == 2) {
  635. checkFilter()
  636. if (filterIsOn) {
  637. $('#' + utilite + '-filter').css('opacity', 0.4)
  638. $('.' + utilite + '-card').each(function () { // only display cards from selected category
  639. $(this).removeClass('card-displayed').addClass('card-hidden')
  640. })
  641. } else {
  642. $('.filter-button').each(function() {
  643. $(this).css('opacity', 0.4)
  644. })
  645. $('.projets-grid div').each(function () { // hide all cards
  646. $(this).removeClass('card-hidden').addClass('card-displayed')
  647. })
  648. }
  649. }
  650. triggerLazyLoading()
  651. checkIfCategoryEmpty() // to hide empty category
  652. function checkIfCategoryEmpty() {
  653. $('.projets-grid').each(function() {
  654. let hiddenCount = 0
  655. $(this).children().each(function() {
  656. if ($(this).hasClass('card-hidden')) { hiddenCount++ }
  657. })
  658. if (hiddenCount == $(this).children().length) { $(this).prev().fadeOut() }
  659. else { $(this).prev().fadeIn() }
  660. })
  661. }
  662. }
  663. function loadProjetIndex() {
  664. animateProjectGrid()
  665. isProjetsIndexLoaded = true
  666. }
  667. function animateProjectGrid() {
  668. const grid = document.querySelector(".projets-grid")
  669. animateCSSGrid.wrapGrid(grid, {duration : 600})
  670. }
  671. function resetFilters() {
  672. Object.keys(filterObj).forEach(v => filterObj[v] = false)
  673. }
  674. function filterWhenEntering() {
  675. let searchParam = new URLSearchParams(window.location.search)
  676. if (searchParam.has('filter')) {
  677. switch (searchParam.get('filter')) {
  678. case 'publique':
  679. filterCards('publique')
  680. break
  681. case 'sociale':
  682. filterCards('sociale')
  683. break
  684. case 'culturelle':
  685. filterCards('culturelle')
  686. break
  687. }
  688. }
  689. }
  690. // display reader
  691. function displayReader() {
  692. $('.owl-carousel').owlCarousel()
  693. // initCarrousel()
  694. $('header').fadeOut()
  695. projectTitleIsScrolling = false
  696. checkTitleAutoScroll()
  697. let isProjectHeaderDisplayed = false
  698. $(window).scroll( () => {
  699. if ($(window).scrollTop() > $('#main-project-title').offset().top && !isProjectHeaderDisplayed) {
  700. $('#header-project').css('top', '0vh')
  701. if(isDesktopDevice) {
  702. $('#close-project').addClass('scrolled-cross')
  703. }
  704. isProjectHeaderDisplayed = true
  705. } else if ($(window).scrollTop() < $('#main-project-title').offset().top && isProjectHeaderDisplayed) {
  706. $('#header-project').css('top', '-9vh')
  707. if (isDesktopDevice) {
  708. $('#close-project').removeClass('scrolled-cross')
  709. }
  710. isProjectHeaderDisplayed = false
  711. }
  712. })
  713. }
  714. function leaveReader() {
  715. $(window).off('scroll')
  716. $('header').fadeIn()
  717. if (!$('nav li a[href$=projets]').parent().hasClass('selected')) {
  718. changeNavSelected('projets')
  719. }
  720. disableTitleAutoScroll()
  721. }
  722. function titleAutoScroll() {
  723. if (!projectTitleIsScrolling) {
  724. $('#header-project').append('<div id="gradient-long-title"></div>')
  725. projectTitleIsScrolling = true
  726. }
  727. $('#header-project h2 span').addClass('scrollText')
  728. $('#header-project h2 span').css({
  729. 'transition': 'transform 7s linear',
  730. 'transform': 'translate(-' + parseInt($('#header-project h2 span').width() / 2 + 8) + 'px, 0)'
  731. })
  732. titleScrollTimer = setTimeout( () => {
  733. $('#header-project h2 span').css({'transition': 'none', 'transform': 'translate(0, 0)'})
  734. titleAutoScroll()
  735. }, 7000)
  736. }
  737. function disableTitleAutoScroll() {
  738. $('#gradient-long-title').remove()
  739. $('#header-project h2 span').removeClass('scrollText').css({'transition': 'none', 'transform': 'translate(0, 0)'})
  740. projectTitleIsScrolling = false
  741. }
  742. function checkTitleAutoScroll() {
  743. if (titleScrollTimer != null) { clearTimeout(titleScrollTimer) }
  744. if ($('#header-project h2 span').width() > $('#header-project h2').width() && !projectTitleIsScrolling) {
  745. titleAutoScroll()
  746. } else if ($('#header-project h2 span').width() / 2 < $('#header-project h2').width() && projectTitleIsScrolling) {
  747. $('#header-project h2 span').removeClass('scrollText')
  748. disableTitleAutoScroll()
  749. }
  750. }
  751. // function initCarrousel() {
  752. // let isCarrouselOpen = false, currentImg
  753. // $('#reader img').each((i, el) => {
  754. // $(el).on('click', () => {
  755. // if (!isCarrouselOpen) { displayCarrousel(el) }
  756. // })
  757. // })
  758. // $('#bg-carrousel').on('click', () => {
  759. // hideCarrousel()
  760. // })
  761. // function displayCarrousel(img) {
  762. // // if ($(img).attr('src') == $('#cover-image img').attr('src')) {
  763. // // $('#arrow-left .picto').addClass('disabled')
  764. // // } else {
  765. // // $('#arrow-left .picto').removeClass('disabled')
  766. // // }
  767. // // if ($(img).attr('src') == $('#reader img').last().attr('src')) {
  768. // // $('#arrow-right .picto').addClass('disabled')
  769. // // } else {
  770. // // $('#arrow-right .picto').removeClass('disabled')
  771. // // }
  772. // $('#reader #carrousel figure img').attr('src', $(img).attr('src'))
  773. // currentImg = $(img)
  774. // $('#arrow-left').on('click', () => {
  775. // $('#reader #carrousel figure img').attr('src', $(currentImg).parent().prev().children().first().attr('src'))
  776. // currentImg = $(currentImg).parent().prev().children().first()
  777. // })
  778. // $('#arrow-right').on('click', () => {
  779. // $('#reader #carrousel figure img').attr('src', $(currentImg).parent().next().children().first().attr('src'))
  780. // currentImg = $(currentImg).parent().next().children().first()
  781. // })
  782. // $('#carrousel').css('display', 'block')
  783. // isCarrouselOpen = true
  784. // }
  785. // function hideCarrousel() {
  786. // $('#carrousel').css('display', 'none')
  787. // isCarrouselOpen = false
  788. // }
  789. // }
  790. // show and hide footer
  791. function displayFooter() {
  792. $('footer').fadeIn()
  793. }
  794. function hideFooter() {
  795. $('footer').fadeOut()
  796. }
  797. function hideFooterOnResize() {
  798. if ($('footer').css('display', 'flex') &&
  799. (window.matchMedia('(max-width: 576px)').matches ||
  800. $('.selected').text().trim() == 'Accueil' ||
  801. $('.selected').text().trim() == 'Projets')) {
  802. $('footer').css('display', 'none')
  803. }
  804. }