....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 213.186.33.2  /  Your IP : 216.73.216.250
Web Server : Apache
System : Linux webd003.cluster102.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User : uneseuleoc ( 96096)
PHP Version : 7.4.33
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/uneseuleoc/www/plugins-dist/statistiques/javascript/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/uneseuleoc/www/plugins-dist/statistiques/javascript/spip_d3_statistiques.js
/**
 * Affiche le graphique ou le tableau
 *
 * @param node btn html du bouton
 * @param string id identifiant du graphique
 * @param string to 'svg' ou 'table'
 */
function spip_d3_statistiques_toggle_svg_table(btn, id, to) {
	jQuery(btn).parent().find('.btn').removeClass('btn_on');
	jQuery(btn).addClass('btn_on');
	if (to === 'table') {
		jQuery(id).find('.spip_d3_svg').hide().end().find('.spip_d3_table').show();
	} else {
		jQuery(id).find('.spip_d3_table').hide().end().find('.spip_d3_svg').show();
	}
	const url = parametre_url(window.document.location.href, 'vue', to);
	window.history.replaceState({}, window.document.title, url);
}

/**
 * Recharge le graphique avec cette url json
 *
 * @param node btn html du bouton
 * @param string $id identifiant du graphique
 */
function spip_d3_statistiques_load_json(btn, id) {
	const $btn = jQuery(btn);
	$btn.parent().find('.btn').removeClass('btn_on');
	$btn.addClass('btn_on');

	$btn.closest('.spip_d3_nav').find('.btn--stats-json').attr('href', btn.dataset.jsonAuteur);
	$btn.closest('.spip_d3_nav').find('.btn--stats-csv').attr('href', btn.dataset.csvAuteur);
	$btn.closest('.spip_d3_nav').find('.spip_d3_nav_caption').text(btn.dataset.title);

	const url = parametre_url(window.document.location.href, 'graph', btn.dataset.graph);
	window.history.replaceState({}, window.document.title, url);

	const $id = jQuery(id);
	$id[0].dataset.json = btn.dataset.json;
	$id[0].dataset.title = btn.dataset.title;
	const graph = $id.data('graph');

	graph.updateJson();
}


/**
 * Déclare et crée le graphique et tableau html de l'id demandé.
 *
 * L'url du json de ses données est dans l'attribut data-json.
*/
function spip_d3_statistiques_create(id, options = {}) {
	if (jQuery(id).data('graph')) {
		return;
	}
	const $nav = jQuery(id).parent().find('.spip_d3_nav');
	if ($nav.find('.groupe-btns--stats-graph .btn.btn_on').length) {
		jQuery(id)[0].dataset.json = $nav.find('.groupe-btns--stats-graph .btn.btn_on').data('json');
	}
	const table_visible = !!$nav.find('.btn--stats-to-table.btn_on').length;

	const graph = new Spip_d3_graph(id, {
		language: options.language || 'fr',
		d3_directory: options.d3_directory,
	});
	jQuery(id).data('graph', graph);
	graph.set_dataLoader(data => {
		// ici on peuple les dates manquantes du json
		data.data = graph.fillInDates(data.meta, data.data, currentDate => {
			return {"date": currentDate, "visites": 0};
		});
		graph.update_table(data, true);
		spip_d3_statistiques_update_graph(id, data);
	});

	graph.loading_start();
	Promise.resolve()
	// charger la locale de date avant de créer les axes… sinon ils ne sont pas traduits
	.then(d => graph.localize_d3_time(d))
	.then(() => {
		graph.prepare_table(table_visible);
		spip_d3_statistiques_prepare_graph(id, !table_visible);
		graph.updateJson();
	});

}

/**
 * On prépare le svg, les définitions d'axes, d'histogrammes, etc...
 *
 * On stocke ces infos dans l'objet "modele" que l'on attribut à svg.datum()
 * pour être exploité plus tard dans la fonction d'update
 *
 * Cette fonction n'a pas connaissance encore des données du json.
 */
function spip_d3_statistiques_prepare_graph(id, visible = true) {

	const inner = d3.select(id).select('.spip_d3_graph_inner');

	const dimensions = {
		height: 300,
		width: 800,
		margin: {
			top: 30,
			right: 30,
			bottom: 30,
			left: 60
		}
	};
	dimensions.inner = {
		width: dimensions.width - dimensions.margin.left - dimensions.margin.right,
		height: dimensions.height - dimensions.margin.top - dimensions.margin.bottom,
	}

	const modele = {}
	modele.dimensions = dimensions;
	modele.parseTime = d3.timeParse("%Y-%m-%d");
	modele.dateFormat = d3.timeFormat("%d %B %Y");

	const x = d3.scaleTime().range([0, dimensions.inner.width ]);
	const y = d3.scaleLinear().range([dimensions.inner.height, 0]);
	modele.x = x;
	modele.y = y;

	modele.xAxis = g => g
		.attr("transform", "translate(0, " + dimensions.inner.height + ")")
		.call(d3.axisBottom(x).ticks(dimensions.width / 80)/*.tickSizeOuter(0)*/)

	modele.yAxis = g => g
		.call(d3.axisLeft(y).ticks(dimensions.inner.height / 40));

	modele.line = d3.line()
		.curve(d3.curveBasis)
		.x(d => modele.x(d.date))
		.y(d => modele.y(d.moyenne_mobile))

	// Create one bin per month, use an offset to include the first and last months
	modele.histogram = d3.bin()
		.value(d => d.date);

	modele.rollingSum = (data, windowSize = 7) => {
		const summed = data.map((d, i) => {
			const start = Math.max(0, i - windowSize)
			const end = i + 1;
			d.moyenne_mobile = Math.round(d3.sum(data.slice(start, end), d => d.visites) / (end - start));
			return d;
		})
		return summed;
	}

	const svg_outer = inner
		.append('svg')
		.attr("viewBox", `0 0 ${dimensions.width} ${dimensions.height}`)
		.attr("class", "spip_d3_svg");

	if (!visible) {
		svg_outer.style("display", "none");
	}

	const svg = svg_outer
		.append("g")
		.attr("class", "spip_d3_svg_inner")
		.attr("transform", "translate(" + dimensions.margin.left + ", " + dimensions.margin.top + ")");
	svg
		.append("g")
		.attr("class", "spip_d3_svg_grid spip_d3_svg_grid--horizontal")
		.call(
			d3.axisLeft(modele.y)
			.ticks(dimensions.inner.height / 40)
			.tickSize(-dimensions.inner.width)
			.tickFormat("")
		)

	const tooltip = inner
		.append("div")
		.attr("class", "spip_d3_tooltip")
		.style("opacity", 0);
	tooltip
		.append("ul")
		.attr("class", "spip_d3_tooltip_list");


	modele.tooltip = {
		show: () => {
			tooltip
				.transition()
				.duration(200)
				.style("opacity", 1)
		},
		hide: () => {
			tooltip
				.transition()
				.duration(200)
				.style("opacity", 0)
		},
		empty: () => {
			tooltip.select('ul').html("");
		},
		add: (key, label, value) => {
			const item = tooltip.select('ul')
				.append('li')
				.attr("class", "spip_d3_tooltip_data spip_d3_tooltip_data--" + key);
			item
				.append("strong")
				.attr("class", "spip_d3_tooltip_label")
				.text(label + " :");
			item
				.append("span")
				.attr("class", "spip_d3_tooltip_value")
				.text(value);
		},
		update: (event) => {
			const data = modele.data;
			const xp = d3.pointer(event)[0];
			const x0 = x.invert(xp);
			const i = d3.bisector(d => d.date).left(data, x0);
			d = data[i - 1];

			const pos = inner.node().getBoundingClientRect();
			tooltip.style("top", (event.clientY - pos.y - 30) + "px");

			if (xp < dimensions.inner.width / 2) {
				tooltip.style("right", "").style("left", (event.clientX - pos.x + 30) + "px");
			} else {
				tooltip.style("left", "").style("right", (pos.right - event.clientX + 30) + "px");
			}
			modele.tooltip.empty();
			if (d) {
				modele.tooltip.add('date', modele.meta.translations.date, d.label);
				modele.tooltip.add('visites', modele.meta.translations.visites, d.visites);
				modele.tooltip.add('moyenne', modele.meta.translations.moyenne + " (MM" + modele.rollingSumWindowSize + ")", d.moyenne_mobile);
			} else {
				modele.tooltip.add('date', modele.meta.translations.date, '?');
			}
		}
	}

	svg
		.append("rect")
		.attr("class", "spip_d3_svg_overlay")
		.attr("width", modele.dimensions.inner.width)
		.attr("height", modele.dimensions.inner.height)
		.on("mouseover", modele.tooltip.show)
		.on("mouseout", modele.tooltip.hide)
		.on("mousemove", modele.tooltip.update);

	svg
		.append('g')
		.attr("class", "spip_d3_svg_histogram")
		.on("mouseover", modele.tooltip.show)
		.on("mouseout", modele.tooltip.hide)
		.on("mousemove", modele.tooltip.update);

	svg
		.append('path')
		.attr("class", "spip_d3_svg_line spip_d3_svg_line--average");

	svg
		.append('g')
		.attr("class", "spip_d3_svg_xaxis");

	svg
		.append('g')
		.attr("class", "spip_d3_svg_yaxis")

	svg.datum(modele);
	return svg;
}


/**
 * On crée les dessins sur le svg, grace aux données obtenues
 */
function spip_d3_statistiques_update_graph(id, _data) {

	if (d3.select(id).select('.spip_d3_svg_inner').empty()) {
		spip_d3_statistiques_prepare_graph(id);
	}

	const svg = d3.select(id).select('.spip_d3_svg_inner');
	const modele = svg.datum();
	const x = modele.x;
	const y = modele.y;

	const data = _data.data;
	const meta = _data.meta;
	modele.data = data; // pour tooltip
	modele.meta = meta; // pour tooltip

	// format the data
	data.forEach(d => {
		d.label = d.date;
		d.date = luxon.DateTime.fromISO(d.date);
		d.visites = +d.visites;
	});

	x.domain(d3.extent(data, d => d.date));

	modele.histogram.domain(x.domain())

	let rollingSumWindowSize = 7;
	if (meta.unite === 'day') {
		modele.histogram.thresholds(x.ticks(d3.timeDay));
	}  else if (meta.unite === 'week') {
		rollingSumWindowSize = 4;
		modele.histogram.thresholds(x.ticks(d3.timeWeek));
	} else if (meta.unite === 'month') {
		rollingSumWindowSize = 6;
		modele.histogram.thresholds(x.ticks(d3.timeMonth));
	} else if (meta.unite === 'year') {
		rollingSumWindowSize = 3;
		modele.histogram.thresholds(x.ticks(d3.timeYear));
	} else {
		throw "meta.unite not in day|month|year";
	}

	modele.rollingSumWindowSize = rollingSumWindowSize;
	modele.rollingSum(data, rollingSumWindowSize);

	// group the data for the bars
	const bins = modele.histogram(data);

	// format the sum
	bins.forEach((d, i) => {
		d.visites = +0;
		d.moyenne_mobile = +0;
		if (d.length) {
			for (let j = 0; j < d.length; j++) {
				d.visites += d[j].visites;
				d.moyenne_mobile += d[j].moyenne_mobile;
			}
			d.label = d[0].label;
			d.date = d[0].date;
		}
	});

	y.domain([0, d3.max(bins, d => d.visites)]);

	svg
		.select('.spip_d3_svg_histogram')
		.selectAll("rect")
		.data(bins)
		.join('rect')
		.attr("class", "spip_d3_svg_bar spip_d3_svg_bar--primary")
		.attr("x", 1)
		.attr("transform", d =>  "translate(" + x(d.x0) + "," + y(d.visites) + ")")
		.attr("width", d => x(d.x1) - x(d.x0) - .5)
		.attr("height", d => modele.dimensions.inner.height - y(d.visites))

	svg
		.select('.spip_d3_svg_line')
		.datum(data)
		.attr("d", modele.line);

	svg.select('.spip_d3_svg_xaxis').call(modele.xAxis);
	svg.select('.spip_d3_svg_yaxis').call(modele.yAxis);
}

Youez - 2016 - github.com/yon3zu
LinuXploit