{"tag":"library","articles":{"projects\/tinyfingerprint":{"key":"projects\/tinyfingerprint","type":"article","published":true,"meta":{"createdAt":"2023-05-17T17:52:37+02:00","publishedAt":"2023-05-17T17:52:37+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/tinyfingerprint.avris.it\/","displayUrl":null}],"category":"projects","subcategory":null,"slug":"tinyfingerprint"},"content":{"en":{"slug":"tinyfingerprint","title":"tinyfingerprint","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252.51048532055\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACBklEQVRIia1Wy27jMAwcUi87SFMgQY655P+\/aU89FdtukMJwHElkD10T6WLbqEEIGLAkShqNZmiTqiquxPn4Cy9DQikCZgYzQ1WxXC6xWq2uTW8OEQE3ZXKPvuvgnIOqYhiGj25um\/6ToBaGDuMEzhNEBEQEIkKtFc45y6m1GnMPDw+fxlpDRNoA5SoI7v5s\/A+Qb0n88\/Ib4zhCVe0hImNkPhMzo5SCGKOxKfKhu91uByK6ulcTIGaG994AzBsBsHcigqoixmigACDnDO89xnHEYrG4DyARMQClFHjvUUqBcw61Vhub2wCsX1UNcEs0AVJVTNOEEAJyziilGCO1VnsvpWC73RqTImLO7Pv+foCYGSEEc45zDo+Pj3Z9s45mvcxtZjb25ty7AWJms7yI4PX1Fc45Y+FSRwCsLDjnEEKwvLsA6vseMcZPevDem7YumZidRkQ31aMmQMfjEcMwYL\/f\/2hxAMZYq6jbKvXhgNPpZMKNMZqYa61m95TSl2vEGK\/avrkwqiqen5\/tikII6PseXdehlIJpmjCOI7qu+zjlX61dnnW5XN6vDnnvsdlskFK66RtFRFYor+U1Aco5g4hwPp\/hvW9a\/DJSSt9e502A3t7eEELAer1uov7faJAqAMCLCHLOZtuvAOWcoao4HA54enpCSumT\/ReLxbf\/R9dET0QIIeAdmqdWoOSD4fwAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252.51048532055\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic, privacy-friendly library for browser fingerprinting in nodejs\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022505.0209706411\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACBklEQVRIia1Wy27jMAwcUi87SFMgQY655P+\/aU89FdtukMJwHElkD10T6WLbqEEIGLAkShqNZmiTqiquxPn4Cy9DQikCZgYzQ1WxXC6xWq2uTW8OEQE3ZXKPvuvgnIOqYhiGj25um\/6ToBaGDuMEzhNEBEQEIkKtFc45y6m1GnMPDw+fxlpDRNoA5SoI7v5s\/A+Qb0n88\/Ib4zhCVe0hImNkPhMzo5SCGKOxKfKhu91uByK6ulcTIGaG994AzBsBsHcigqoixmigACDnDO89xnHEYrG4DyARMQClFHjvUUqBcw61Vhub2wCsX1UNcEs0AVJVTNOEEAJyziilGCO1VnsvpWC73RqTImLO7Pv+foCYGSEEc45zDo+Pj3Z9s45mvcxtZjb25ty7AWJms7yI4PX1Fc45Y+FSRwCsLDjnEEKwvLsA6vseMcZPevDem7YumZidRkQ31aMmQMfjEcMwYL\/f\/2hxAMZYq6jbKvXhgNPpZMKNMZqYa61m95TSl2vEGK\/avrkwqiqen5\/tikII6PseXdehlIJpmjCOI7qu+zjlX61dnnW5XN6vDnnvsdlskFK66RtFRFYor+U1Aco5g4hwPp\/hvW9a\/DJSSt9e502A3t7eEELAer1uov7faJAqAMCLCHLOZtuvAOWcoao4HA54enpCSumT\/ReLxbf\/R9dET0QIIeAdmqdWoOSD4fwAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022505.0209706411\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic, privacy-friendly library for browser fingerprinting in nodejs\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["fingerprint","server-side","javascript","nodejs","library","minimalistic"],"hasMore":false,"image":"https:\/\/avris.it\/image\/tinyfingerprint_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinyfingerprint_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126.25524266028\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic, privacy-friendly library for browser fingerprinting in nodejs\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinyfingerprint_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinyfingerprint_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126.25524266028\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic, privacy-friendly library for browser fingerprinting in nodejs\u003C\/p\u003E","words":9,"readTime":null,"lang":"en"}}},"projects\/tinytranslator":{"key":"projects\/tinytranslator","type":"article","published":true,"meta":{"createdAt":"2023-05-16T17:52:22+02:00","publishedAt":"2023-05-16T17:52:22+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/tinytranslator.avris.it\/","displayUrl":null}],"category":"projects","subcategory":null,"slug":"tinytranslator"},"content":{"en":{"slug":"tinytranslator","title":"tinytranslator","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinytranslator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252.38895558223\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABiklEQVRIicWVwY7iMBBEX9uJnUTsICRu\/P9ncdrlhIRAgV0mibv3FLSH2aFBjKbObbu6ulwtZmbcweHnL\/4ITKVQ1zWqipmx2WwIIdw7\/hAqT9GP5ZIK43K5ICJM04SIvJwMgHgUOv5+J0zvmBlzedM0NE3zPYRGVeovUOMjuF457Pdst9uv5gI4FTqdTkzTRCmFGCOqSlVVpJRIKbkeCiEQY7xb5zK1mbHb7RARcs6sVitEhHEcGcfRRSilRNd1d+tcI0spsV6vSSnRNA1V5erjKbidOncoIjim\/DTcrZZSaNsWVWUYhhs5L7y1bkI5Z97e3h4i8QwhXzAej+z3e8yMnDOLxcL1Y\/7Fy00dQsDMGIYBVX2IzCNwj6zrOoZhAOB6vQIQY\/ye5SoitG1L13U3debl6iXkHbE7GM0MVUVEUFVCCNR17U7ql5r6cDjQ9z2llFsozsdijJgZKSVyzv+9w2vqSlUZx\/HTsCulcLlc6Pue5XLJ+Xy+7bM5wc3s5q2PMKv6GVJK\/AW+Ibv2Kw7IKwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinytranslator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252.38895558223\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic translator library\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinytranslator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022504.77791116447\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABiklEQVRIicWVwY7iMBBEX9uJnUTsICRu\/P9ncdrlhIRAgV0mibv3FLSH2aFBjKbObbu6ulwtZmbcweHnL\/4ITKVQ1zWqipmx2WwIIdw7\/hAqT9GP5ZIK43K5ICJM04SIvJwMgHgUOv5+J0zvmBlzedM0NE3zPYRGVeovUOMjuF457Pdst9uv5gI4FTqdTkzTRCmFGCOqSlVVpJRIKbkeCiEQY7xb5zK1mbHb7RARcs6sVitEhHEcGcfRRSilRNd1d+tcI0spsV6vSSnRNA1V5erjKbidOncoIjim\/DTcrZZSaNsWVWUYhhs5L7y1bkI5Z97e3h4i8QwhXzAej+z3e8yMnDOLxcL1Y\/7Fy00dQsDMGIYBVX2IzCNwj6zrOoZhAOB6vQIQY\/ye5SoitG1L13U3debl6iXkHbE7GM0MVUVEUFVCCNR17U7ql5r6cDjQ9z2llFsozsdijJgZKSVyzv+9w2vqSlUZx\/HTsCulcLlc6Pue5XLJ+Xy+7bM5wc3s5q2PMKv6GVJK\/AW+Ibv2Kw7IKwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinytranslator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022504.77791116447\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic translator library\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["translator","javascript","library","minimalistic"],"hasMore":false,"image":"https:\/\/avris.it\/image\/tinytranslator_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinytranslator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinytranslator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126.19447779112\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic translator library\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinytranslator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinytranslator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126.19447779112\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic translator library\u003C\/p\u003E","words":4,"readTime":null,"lang":"en"}}},"projects\/tinymarkdown":{"key":"projects\/tinymarkdown","type":"article","published":true,"meta":{"createdAt":"2023-05-16T16:52:28+02:00","publishedAt":"2023-05-16T16:52:28+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/tinymarkdown.avris.it\/","displayUrl":null}],"category":"projects","subcategory":null,"slug":"tinymarkdown"},"content":{"en":{"slug":"tinymarkdown","title":"tinymarkdown","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinymarkdown_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022251.53846153846\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB2UlEQVRIia2VXW+bMBSGH3+AATWNIrW9aO\/y\/3\/XtGiL0iwdxGDO2UUHWqZucVReCSEdsP34PcfHRlWVK\/ry7ZWh+4GKoKqICCEEHh4eqKrq2vCb5LP+UmF9f0\/XdQCICNZanHOLwgCYHIde24gZzqgqxhiMMagqqoq19n2iokEUjAHtf6KqlGVJ0zTLAw2iFNZcxCa4v\/WveK6yUvZ995W2bfHeIyIAjONIURSoKiEEhmHAe09KaXbOWov8rruXl5esFGc51LbtvHMRmd93d3efcuMjZTm03+\/puo7tdnsRH8cxeyFjzHIO7XY7TqcTfd9T1zXOOYqimNNU1\/VVp3ILPMuhpmlIKbFarS5c8f59+J\/twDk3n8AJchxHNptNzlJ5QDFGzuczxhhijDjnEBG893NxT6B1Xc+wU0Fba7PTmwUUQmC9XmdN+NHYqqrmfrUI0OFwoO97np+fb250tyoLuyxLvPfEGAHmGpmeJZV1yt7e3kgpAVAUBSklUkpzAdd1vdglm5Wy4\/FI13WICE9PT4QQKMsS5xxlWS4CchNQ0zTz7T51aWvt4unKBkopISKM44i1lpTSRSMMISwHpKoMw\/Df3cYYiTFireXx8fHD75+VMQbvPb8AVxwPhTUnZx0AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinymarkdown_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022251.53846153846\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic library for inline markdown: 9 features \u2013 10 lines of code \u2013 0 dependencies\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tinymarkdown_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022503.07692307692\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB2UlEQVRIia2VXW+bMBSGH3+AATWNIrW9aO\/y\/3\/XtGiL0iwdxGDO2UUHWqZucVReCSEdsP34PcfHRlWVK\/ry7ZWh+4GKoKqICCEEHh4eqKrq2vCb5LP+UmF9f0\/XdQCICNZanHOLwgCYHIde24gZzqgqxhiMMagqqoq19n2iokEUjAHtf6KqlGVJ0zTLAw2iFNZcxCa4v\/WveK6yUvZ995W2bfHeIyIAjONIURSoKiEEhmHAe09KaXbOWov8rruXl5esFGc51LbtvHMRmd93d3efcuMjZTm03+\/puo7tdnsRH8cxeyFjzHIO7XY7TqcTfd9T1zXOOYqimNNU1\/VVp3ILPMuhpmlIKbFarS5c8f59+J\/twDk3n8AJchxHNptNzlJ5QDFGzuczxhhijDjnEBG893NxT6B1Xc+wU0Fba7PTmwUUQmC9XmdN+NHYqqrmfrUI0OFwoO97np+fb250tyoLuyxLvPfEGAHmGpmeJZV1yt7e3kgpAVAUBSklUkpzAdd1vdglm5Wy4\/FI13WICE9PT4QQKMsS5xxlWS4CchNQ0zTz7T51aWvt4unKBkopISKM44i1lpTSRSMMISwHpKoMw\/Df3cYYiTFireXx8fHD75+VMQbvPb8AVxwPhTUnZx0AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/tinymarkdown_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022503.07692307692\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic library for inline markdown: 9 features \u2013 10 lines of code \u2013 0 dependencies\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["markdown","inline","javascript","library","minimalistic"],"hasMore":false,"image":"https:\/\/avris.it\/image\/tinymarkdown_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinymarkdown_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinymarkdown_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.76923076923\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic library for inline markdown: 9 features \u2013 10 lines of code \u2013 0 dependencies\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tinymarkdown_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tinymarkdown_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.76923076923\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ea minimalistic library for inline markdown: 9 features \u2013 10 lines of code \u2013 0 dependencies\u003C\/p\u003E","words":11,"readTime":null,"lang":"en"}}},"blog\/society\/ocz-just-some-googly-eyes":{"key":"blog\/society\/ocz-just-some-googly-eyes","type":"article","published":true,"meta":{"createdAt":"2019-10-16T17:27:18+02:00","publishedAt":"2019-10-16T20:23:00+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/ocz.avris.it\/","displayUrl":"Demo"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Ocz","displayUrl":null},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/www.npmjs.com\/package\/avris-ocz","displayUrl":null}],"category":"blog","subcategory":"society","slug":"ocz-just-some-googly-eyes"},"content":{"en":{"slug":"ocz-just-some-googly-eyes","title":"Ocz \u2013 Just some googly eyes.","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-ocz_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHhUlEQVRIiX2Xy69lRRXGf+tRtfc595776tsXmoZu3gqoHYhGEmJoSRCIQYPGB5oQHehA48A\/wbkzB0bjWEfGCRKj0QgkkCgaH4AtEexuHg1p+nHvPfd19q5aDvbpxqixsl\/Jrtr11ffVWuvbcuzGuyJKRQiiVoiKuVNLIQhUBFfDVEnuzGYH1FohAiIQQEQQhiYiiAgQXGkRMT\/r1TtREQEVwdwxEZpmhEcIEUGpBQkQoJSCMHxYVQegolArSZV+PgEi835c7S8CIKjKe5PLlWchakHUiHhvnCEkNbQW\/MoAQQkqEaAhiA6TEYKqA0JfKoagCCGKqc7ZGBaCDO\/mx\/xiuBuzWYcIRAwLFFF0PtZUcTOSKh6iUMuc4IERIpAQVA03xUQwUdwUiUqtlVrL8AH3YfW1ompXpVIRolaCYHllhcsXLwEVQhCHqAVVgQAzJZmR\/AogAVSgztkSENG5DIaimBnZEuOmgejZ3dujcadJTvZErZVSevpSQBj2S60AHLlmg4PtKVAH0iJQzXNQiukgcTbFRRMRHRIGUtGrm1RQs4FaS6goKoaKs9AssDpa5tJ0Ew0lStB4Qj1DFEKEvu8GhgRuPHaMt0+fRSSQAFNBCCAhEnPJlGSKa8r0wTxi7EqsgOrAjhqmRnYnW0IxRBJNTtx0eJGd3SkHXcc1124w29tlurWNiZBdqVG57xP38+rLp1jKDUEMkQWoDqKogggkU7IbHpqQNJcLoQaYKKqGiuLmuBrZMy5CMidJImnD2toyn\/nK51hbXeG3P\/0Fr585izWLJB+iabK8yH0P3M9LTz\/HSjsCChExgFFBBcwE04E1d8HJDdI7tcZcXwBF1FBzRAw3RzXhZvMzcfKRj\/H4N7\/AKy\/8jSe\/9xMShduPXEfUyvbOFM\/Gl7\/zbV742VNcv7TErHTU6Ikog3Q6j6407KGcFFNwaReoXUFqHfJQAGKIOGqJZI6qkcxpU2bszle\/8Vkeeuwk00vbPPWDJ8k6YnXccsut17Gz+S6bu\/s88K0vkVSoZ97g\/Uc2mO7tst\/PKLWn1A60ktwwE9yV5EJKhst4CZn1UCoBwx5BEUmoGOKJrE6bEuOUePyJB3nosZMA\/OXZF0k0TBYnLI4bti\/ucfzDH+ITj96Htw3Pf\/dHbKwvo9GxuRX0faLEACikohqk7LgLKSmeBZfRBHIPBSQUQhEUxEETpk4yJ6fEiRM38anPf\/xqSdh6Z8qhaw5z9PgGx++6gRvuuZmF9SUigtd\/+QwLo0ypi7RNT24qSKVGR9\/PiNqhBqqBuZEbx5PgTJahL0TIACaG6DIc14TiyDwBPvH1R65mZoCHv\/Yg\/9kigjef+QOz8+9y+MZDHGxmup3LLGmHWEUsqLWj9gcIPWqCuZJyxpsG18mEVBjqDIqHkjCyODmMrEZGuefEMY4eXfsvAP\/eaim8+qvfs\/3Kq7QLSrs85vAd19NvLrB1TlCZIXQgmSgJkTpEWHIsZ6wZ4ZOVCaUAc4YMwcNpxWhRWoymCvd+9Nb\/C2Z6fpOXf\/4cswvnGTWAQre3y+6FDpcZ4+WG2pUh9xioJGQul7pjuUWbEX7t2oi+D2qBGoqGohgphITRhtIU4fab1\/8nkL2tXf7+7Iu8+cdTZOkYtXUoHRWig3pg0Ch5pERSTGIuU0JNsZTR3CCpgTzCP7DRsLvfMTsozPpKKZVSKxKCRMWKYCKsr46vgtiZ7nHmlTc5\/efXePOlf9JEx9gLkQpOJWslNMACZkOtlBQkD9wEM0FTQnILySBnyA14iz+6+hY7+5XptGNrpzLtg+0D2J3BfgezXig9\/PD7P2ZvZ4\/L726xc3GLXAqJQqLSamVkPQspWGors3GFSZBCaG2wGVI61APLhtWg6wxjQndgaJvYvDSmo0VO3rUeS21if3+wSm6ZEKfihCQKTtVMXyFEQR0RxXXI2kONM7IJjcJChkmGwwvBkdXCxrqxsCCcPXeZ6d4eJXesXHeUp3\/9O06fO2CprWxsTDjogudf3kEWV9ZCU0bUsJTwpkXU8NzgKWOpQdXITYt5InnGLQ12U4y777yN1p29nZ5DSyPOnnqN5WSstspKC4cWldUFSNqTrGdloef2E2Mun5ty\/twWkxG49By+90F2\/\/ob\/I5Pf5FmcYm+QrswwVODqiPmJE+IGMJQdyQEKRVKQWqgpTI+so4DaS3ouh42enqBA1MOXNhJSk5GmyrVKvtNpbMV1t4Hl6evkUZC4z39pV0W73wILxjT3T2wxGx7G5EdQAcvFIMBH7wQczAVqZW6vw+1cOHtM0gJJAKrhcTgjccpM0nOxJ3lJjFOgmthnGG63\/GRDy7xxiWlXuxZGsHk8lvc9vDd+KUz\/2DWdahnaql4M4L3\/iEQwFNCVZEIogYaAwCtFen7qwa\/dge4GJffOUubW1yE5cUlDi2t4FHZ3d1idWnCn045b58Z8c7mPqcv7DPKQaMzPtm\/gazfckfUUuhnM2p3QFqYICGU2T6amqEc1B7PLcDguQGtgSJIXPHQgxfXCISKieAquIBSyWaoBn3fIRQ2Js5ya1zcG2xu43DvcfgXoycudg\/N7GgAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-ocz_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFair warning: this library is pretty useless. And only moderately fun... \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cp\u003EBut it seemed like a cool way to learn a bit about web components, so here it is: a component that creates googly eyes that follow your mouse.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-ocz_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHhUlEQVRIiX2Xy69lRRXGf+tRtfc595776tsXmoZu3gqoHYhGEmJoSRCIQYPGB5oQHehA48A\/wbkzB0bjWEfGCRKj0QgkkCgaH4AtEexuHg1p+nHvPfd19q5aDvbpxqixsl\/Jrtr11ffVWuvbcuzGuyJKRQiiVoiKuVNLIQhUBFfDVEnuzGYH1FohAiIQQEQQhiYiiAgQXGkRMT\/r1TtREQEVwdwxEZpmhEcIEUGpBQkQoJSCMHxYVQegolArSZV+PgEi835c7S8CIKjKe5PLlWchakHUiHhvnCEkNbQW\/MoAQQkqEaAhiA6TEYKqA0JfKoagCCGKqc7ZGBaCDO\/mx\/xiuBuzWYcIRAwLFFF0PtZUcTOSKh6iUMuc4IERIpAQVA03xUQwUdwUiUqtlVrL8AH3YfW1ompXpVIRolaCYHllhcsXLwEVQhCHqAVVgQAzJZmR\/AogAVSgztkSENG5DIaimBnZEuOmgejZ3dujcadJTvZErZVSevpSQBj2S60AHLlmg4PtKVAH0iJQzXNQiukgcTbFRRMRHRIGUtGrm1RQs4FaS6goKoaKs9AssDpa5tJ0Ew0lStB4Qj1DFEKEvu8GhgRuPHaMt0+fRSSQAFNBCCAhEnPJlGSKa8r0wTxi7EqsgOrAjhqmRnYnW0IxRBJNTtx0eJGd3SkHXcc1124w29tlurWNiZBdqVG57xP38+rLp1jKDUEMkQWoDqKogggkU7IbHpqQNJcLoQaYKKqGiuLmuBrZMy5CMidJImnD2toyn\/nK51hbXeG3P\/0Fr585izWLJB+iabK8yH0P3M9LTz\/HSjsCChExgFFBBcwE04E1d8HJDdI7tcZcXwBF1FBzRAw3RzXhZvMzcfKRj\/H4N7\/AKy\/8jSe\/9xMShduPXEfUyvbOFM\/Gl7\/zbV742VNcv7TErHTU6Ikog3Q6j6407KGcFFNwaReoXUFqHfJQAGKIOGqJZI6qkcxpU2bszle\/8Vkeeuwk00vbPPWDJ8k6YnXccsut17Gz+S6bu\/s88K0vkVSoZ97g\/Uc2mO7tst\/PKLWn1A60ktwwE9yV5EJKhst4CZn1UCoBwx5BEUmoGOKJrE6bEuOUePyJB3nosZMA\/OXZF0k0TBYnLI4bti\/ucfzDH+ITj96Htw3Pf\/dHbKwvo9GxuRX0faLEACikohqk7LgLKSmeBZfRBHIPBSQUQhEUxEETpk4yJ6fEiRM38anPf\/xqSdh6Z8qhaw5z9PgGx++6gRvuuZmF9SUigtd\/+QwLo0ypi7RNT24qSKVGR9\/PiNqhBqqBuZEbx5PgTJahL0TIACaG6DIc14TiyDwBPvH1R65mZoCHv\/Yg\/9kigjef+QOz8+9y+MZDHGxmup3LLGmHWEUsqLWj9gcIPWqCuZJyxpsG18mEVBjqDIqHkjCyODmMrEZGuefEMY4eXfsvAP\/eaim8+qvfs\/3Kq7QLSrs85vAd19NvLrB1TlCZIXQgmSgJkTpEWHIsZ6wZ4ZOVCaUAc4YMwcNpxWhRWoymCvd+9Nb\/C2Z6fpOXf\/4cswvnGTWAQre3y+6FDpcZ4+WG2pUh9xioJGQul7pjuUWbEX7t2oi+D2qBGoqGohgphITRhtIU4fab1\/8nkL2tXf7+7Iu8+cdTZOkYtXUoHRWig3pg0Ch5pERSTGIuU0JNsZTR3CCpgTzCP7DRsLvfMTsozPpKKZVSKxKCRMWKYCKsr46vgtiZ7nHmlTc5\/efXePOlf9JEx9gLkQpOJWslNMACZkOtlBQkD9wEM0FTQnILySBnyA14iz+6+hY7+5XptGNrpzLtg+0D2J3BfgezXig9\/PD7P2ZvZ4\/L726xc3GLXAqJQqLSamVkPQspWGors3GFSZBCaG2wGVI61APLhtWg6wxjQndgaJvYvDSmo0VO3rUeS21if3+wSm6ZEKfihCQKTtVMXyFEQR0RxXXI2kONM7IJjcJChkmGwwvBkdXCxrqxsCCcPXeZ6d4eJXesXHeUp3\/9O06fO2CprWxsTDjogudf3kEWV9ZCU0bUsJTwpkXU8NzgKWOpQdXITYt5InnGLQ12U4y777yN1p29nZ5DSyPOnnqN5WSstspKC4cWldUFSNqTrGdloef2E2Mun5ty\/twWkxG49By+90F2\/\/ob\/I5Pf5FmcYm+QrswwVODqiPmJE+IGMJQdyQEKRVKQWqgpTI+so4DaS3ouh42enqBA1MOXNhJSk5GmyrVKvtNpbMV1t4Hl6evkUZC4z39pV0W73wILxjT3T2wxGx7G5EdQAcvFIMBH7wQczAVqZW6vw+1cOHtM0gJJAKrhcTgjccpM0nOxJ3lJjFOgmthnGG63\/GRDy7xxiWlXuxZGsHk8lvc9vDd+KUz\/2DWdahnaql4M4L3\/iEQwFNCVZEIogYaAwCtFen7qwa\/dge4GJffOUubW1yE5cUlDi2t4FHZ3d1idWnCn045b58Z8c7mPqcv7DPKQaMzPtm\/gazfckfUUuhnM2p3QFqYICGU2T6amqEc1B7PLcDguQGtgSJIXPHQgxfXCISKieAquIBSyWaoBn3fIRQ2Js5ya1zcG2xu43DvcfgXoycudg\/N7GgAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-ocz_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFair warning: this library is pretty useless. And only moderately fun... \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cp\u003EBut it seemed like a cool way to learn a bit about web components, so here it is: a component that creates googly eyes that follow your mouse.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["css variables","googly eyes","javascript","js","library","web components"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-ocz_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-ocz_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-ocz_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFair warning: this library is pretty useless. And only moderately fun... \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cp\u003EBut it seemed like a cool way to learn a bit about web components, so here it is: a component that creates googly eyes that follow your mouse.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-ocz_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-ocz_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFair warning: this library is pretty useless. And only moderately fun... \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cp\u003EBut it seemed like a cool way to learn a bit about web components, so here it is: a component that creates googly eyes that follow your mouse.\u003C\/p\u003E","words":39,"readTime":null,"lang":"en"}}},"projects\/avris-sorter":{"key":"projects\/avris-sorter","type":"article","published":true,"meta":{"createdAt":"2019-10-13T14:09:02+02:00","publishedAt":"2019-10-13T14:06:00+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/sorter.avris.it\/","displayUrl":"Demo"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Sorter","displayUrl":null},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/www.npmjs.com\/package\/avris-sorter","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-sorter"},"content":{"en":{"slug":"avris-sorter","title":"Avris Sorter","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-sorter_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHkElEQVRIiX2XyY8kRxXGf2+JyKyqrl5m6cEe8HgBgzEwwjLCkoU8WDK2hQwCxC4hOMABxIE\/gTs3DgjEGU6ICxgJBMK2ZEtsYjHGWNh4xstgxp7ppbq7qjIjHoesGSNAhDIyU8pYvvi+ePG+lBtuvD2iVIQgaoWomDu1FIJARXA1TJXkznK5oNYKERCBACKCMBQRQUSA4GqJiFWt155ERQRUBHPHRGiaER4hRASlFiRAgFIKwjCwqg5ARaFWkir9agJEVu241l4EQFCV1yeXq+9C1IKoEfF6P0NIamgt+NUOghJUIkBDEB0mIwRVB4S+VAxBEUIUU12xMSwEGb6trtXNcDeWyw4RiBgWKKLoqq+p4mYkVTxEoZYVwQMjRCAhqBpuiolgorgpEpVaK7WWYQD3YfW1omrXpFIRolaCYGNzk53LV4AKIYhD1IKqQICZksxIfhWQACpQV2wJiOhKBkNRzIxsiXHTQPQcHh3RuNMkJ3ui1kopPX0pIAz7pVYArju1zWJ\/BtSBtAhU8wqUYjpInE1x0UREh4SBVPTaJhXUbKDWEiqKiqHiTJoJW6MNrsx20VCiBI0n1DNEIUTo+25gSODMDTfwj+cvIBJIgKkgBJAQiZVkSjLFNWX6YBUxdjVWQHVgRw1TI7uTLaEYIokmJ246ucbB4YxF13HqDdssjw6Z7e1jImRXalTu\/sA9PPvU06znhiCGyAJUB1FUQQSSKdkND01IWsmFUANMFFVDRXFzXI3sGRchmZMkkbTh2LENPvr5j3Nsa5Nf\/uAnvHD+BaxZI\/kQTdONNe6+9x7+\/MjjbLYjoBARAxgVVMBMMB1Ycxec3CC9U2us9AVQRA01R8Rwc1QTbraqiXMPvo9Pf+WTPPObv\/Cjb36fROHW664namX\/YIZn47Nf\/xq\/+eHDvHF9nWXpqNETUQbpdBVdadhDOSmm4NJOqF1Bah3OoQDEEHHUEskcVSOZ06bM2J0vfPlj3P+Rc8yu7PPwt39E1hFb45Zb3nw9B7uvsns4596vfoakQj3\/Im+7bpvZ0SHzfkmpPaV2oJXkhpngriQXUjJcxuvIsodSCRj2CIpIQsUQT2R12pQYp8SnP3cf93\/kHAB\/fOxJEg3TtSlr44b9y0ecufNdfOChu\/G24YlvfJftExtodOzuBX2fKDEACqmoBik77kJKimfBZTSF3EMBCYVQBAVx0ISpk8zJKXH27E186BPvv5YS9l6ZcfzUSU6f2ebM7W\/iTXfczOTEOhHBCz99lMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTDegLETKAiSG6DMc1oTiyOgA\/96UHr53MAA988T7+s0QELz36W5aXXuXkjcdZ7Ga6gx3WtUOsIhbU2lH7BUKPmmCupJzxpsF1OiUVhjyD4qEkjCxODiOrkVHuOHsDp08f+y8A\/15qKTz7s1+z\/8yztBOl3Rhz8rY30u9O2LsoqCwROpBMlIRIHSIsOZYz1ozw6eaUUoAVQ4bg4bRitCgtRlOFu9775v8LZnZpl6d+\/DjL1y4xagCF7uiQw9c6XJaMNxpqV4azx0AlISu51B3LLdqM8DccG9H3QS1QQ9FQFCOFkDDaUJoi3Hrzif8J5GjvkL8+9iQv\/e5psnSM2jqkjgrRQV0YNEoeKZEUk1jJlFBTLGU0N0hqII\/wd2w3HM47lovCsq+UUim1IiFIVKwIJsKJrfE1EAezI84\/8xLP\/+E5Xvrz32miY+yFSAWnkrUSGmAByyFXSgqSB26CmaApIbmFZJAz5Aa8xR\/aepmDeWU269g7qMz6YH8Bh0uYd7DshdLDd771PY4Ojth5dY+Dy3vkUkgUEpVWKyPrmaRgva0sxxWmQQqhtcFmSOlQDywbVoOuM4wp3cLQNrF7ZUxHi5y7\/USst4n5fLBKbpkQp+KEJApO1UxfIURBHRFlMh4zalqW8znZjFEynMokwzTDyUlw3VZh+4QxmQgXLu4wOzqi5I7N60\/zyM9\/xfMXF6y3le3tKYsueOKpA2Rt81hoyogalhLetIganhs8ZSw1qBq5aTFPJM+4Jd575x2kCEZNw2LecfrUNrJcYLXw2vmXyf2czRaOrylbE0jak6xnc9Jz69kxOxdnXLq4x3QELj0n77qPwz\/9Ar\/tw5+iWVunr9BOpnhqUHXEnOQJEUMY8o6EIKVCKSzWxmxtrNGocPDqDldKJlmi1p7dvMX6SFm4cJCUnIw2VapV5k2ls02OvRV2Zs+RRkLjPf2VQ9befj9eMGaHR2CJ5f4+IgeADl4oBgM+eCFWYCpSK\/+8MOcvtZDNkBJIBFYLicEbj1NmmpypOxtNYpwE18I4w2ze8Z53rvPiFaVe7lkfwXTnZd7ywLvxK+f\/xrLrUM\/UUvFmBK\/\/QyCAp4SqIhFEDTQGAFor0vfXDH7tFrgYO69coM0tLsLG2jrH1zfxqBwe7rG1PuX3Tzv\/OD\/ild05z782Z5SDRpd8sH8ROXHLbVFLoV8uqd2CNJkiIZTlHE3NkA5qj+cWYPDcgNZAESSueujBi2sEQsVEcBVcQKlkM1SDvu8QCttTZ6M1Lh8NNrdxuOsM\/AtA9jdb2ZxdiwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-sorter_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ELightweight sorting of tables.\u003C\/p\u003E\n\u003Cp\u003EJust add \u003Ccode\u003E[data-sort]\u003C\/code\u003E attributes to the \u003Ccode\u003Eth\u003C\/code\u003E elements in columns you\u2019d like to sort a table by, include ~1kB of JS \u0026amp; CSS, and initialise with \u003Ccode\u003Esorter()\u003C\/code\u003E \u2013 and that\u2019s it!\u003C\/p\u003E\n\u003Cp\u003EFor installation instructions and more customisation options, you can check out the \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Sorter\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E readme file\u003C\/a\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-sorter_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHkElEQVRIiX2XyY8kRxXGf2+JyKyqrl5m6cEe8HgBgzEwwjLCkoU8WDK2hQwCxC4hOMABxIE\/gTs3DgjEGU6ICxgJBMK2ZEtsYjHGWNh4xstgxp7ppbq7qjIjHoesGSNAhDIyU8pYvvi+ePG+lBtuvD2iVIQgaoWomDu1FIJARXA1TJXkznK5oNYKERCBACKCMBQRQUSA4GqJiFWt155ERQRUBHPHRGiaER4hRASlFiRAgFIKwjCwqg5ARaFWkir9agJEVu241l4EQFCV1yeXq+9C1IKoEfF6P0NIamgt+NUOghJUIkBDEB0mIwRVB4S+VAxBEUIUU12xMSwEGb6trtXNcDeWyw4RiBgWKKLoqq+p4mYkVTxEoZYVwQMjRCAhqBpuiolgorgpEpVaK7WWYQD3YfW1omrXpFIRolaCYGNzk53LV4AKIYhD1IKqQICZksxIfhWQACpQV2wJiOhKBkNRzIxsiXHTQPQcHh3RuNMkJ3ui1kopPX0pIAz7pVYArju1zWJ\/BtSBtAhU8wqUYjpInE1x0UREh4SBVPTaJhXUbKDWEiqKiqHiTJoJW6MNrsx20VCiBI0n1DNEIUTo+25gSODMDTfwj+cvIBJIgKkgBJAQiZVkSjLFNWX6YBUxdjVWQHVgRw1TI7uTLaEYIokmJ246ucbB4YxF13HqDdssjw6Z7e1jImRXalTu\/sA9PPvU06znhiCGyAJUB1FUQQSSKdkND01IWsmFUANMFFVDRXFzXI3sGRchmZMkkbTh2LENPvr5j3Nsa5Nf\/uAnvHD+BaxZI\/kQTdONNe6+9x7+\/MjjbLYjoBARAxgVVMBMMB1Ycxec3CC9U2us9AVQRA01R8Rwc1QTbraqiXMPvo9Pf+WTPPObv\/Cjb36fROHW664namX\/YIZn47Nf\/xq\/+eHDvHF9nWXpqNETUQbpdBVdadhDOSmm4NJOqF1Bah3OoQDEEHHUEskcVSOZ06bM2J0vfPlj3P+Rc8yu7PPwt39E1hFb45Zb3nw9B7uvsns4596vfoakQj3\/Im+7bpvZ0SHzfkmpPaV2oJXkhpngriQXUjJcxuvIsodSCRj2CIpIQsUQT2R12pQYp8SnP3cf93\/kHAB\/fOxJEg3TtSlr44b9y0ecufNdfOChu\/G24YlvfJftExtodOzuBX2fKDEACqmoBik77kJKimfBZTSF3EMBCYVQBAVx0ISpk8zJKXH27E186BPvv5YS9l6ZcfzUSU6f2ebM7W\/iTXfczOTEOhHBCz99lMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTDegLETKAiSG6DMc1oTiyOgA\/96UHr53MAA988T7+s0QELz36W5aXXuXkjcdZ7Ga6gx3WtUOsIhbU2lH7BUKPmmCupJzxpsF1OiUVhjyD4qEkjCxODiOrkVHuOHsDp08f+y8A\/15qKTz7s1+z\/8yztBOl3Rhz8rY30u9O2LsoqCwROpBMlIRIHSIsOZYz1ozw6eaUUoAVQ4bg4bRitCgtRlOFu9775v8LZnZpl6d+\/DjL1y4xagCF7uiQw9c6XJaMNxpqV4azx0AlISu51B3LLdqM8DccG9H3QS1QQ9FQFCOFkDDaUJoi3Hrzif8J5GjvkL8+9iQv\/e5psnSM2jqkjgrRQV0YNEoeKZEUk1jJlFBTLGU0N0hqII\/wd2w3HM47lovCsq+UUim1IiFIVKwIJsKJrfE1EAezI84\/8xLP\/+E5Xvrz32miY+yFSAWnkrUSGmAByyFXSgqSB26CmaApIbmFZJAz5Aa8xR\/aepmDeWU269g7qMz6YH8Bh0uYd7DshdLDd771PY4Ojth5dY+Dy3vkUkgUEpVWKyPrmaRgva0sxxWmQQqhtcFmSOlQDywbVoOuM4wp3cLQNrF7ZUxHi5y7\/USst4n5fLBKbpkQp+KEJApO1UxfIURBHRFlMh4zalqW8znZjFEynMokwzTDyUlw3VZh+4QxmQgXLu4wOzqi5I7N60\/zyM9\/xfMXF6y3le3tKYsueOKpA2Rt81hoyogalhLetIganhs8ZSw1qBq5aTFPJM+4Jd575x2kCEZNw2LecfrUNrJcYLXw2vmXyf2czRaOrylbE0jak6xnc9Jz69kxOxdnXLq4x3QELj0n77qPwz\/9Ar\/tw5+iWVunr9BOpnhqUHXEnOQJEUMY8o6EIKVCKSzWxmxtrNGocPDqDldKJlmi1p7dvMX6SFm4cJCUnIw2VapV5k2ls02OvRV2Zs+RRkLjPf2VQ9befj9eMGaHR2CJ5f4+IgeADl4oBgM+eCFWYCpSK\/+8MOcvtZDNkBJIBFYLicEbj1NmmpypOxtNYpwE18I4w2ze8Z53rvPiFaVe7lkfwXTnZd7ywLvxK+f\/xrLrUM\/UUvFmBK\/\/QyCAp4SqIhFEDTQGAFor0vfXDH7tFrgYO69coM0tLsLG2jrH1zfxqBwe7rG1PuX3Tzv\/OD\/ild05z782Z5SDRpd8sH8ROXHLbVFLoV8uqd2CNJkiIZTlHE3NkA5qj+cWYPDcgNZAESSueujBi2sEQsVEcBVcQKlkM1SDvu8QCttTZ6M1Lh8NNrdxuOsM\/AtA9jdb2ZxdiwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-sorter_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ELightweight sorting of tables.\u003C\/p\u003E\n\u003Cp\u003EJust add \u003Ccode\u003E[data-sort]\u003C\/code\u003E attributes to the \u003Ccode\u003Eth\u003C\/code\u003E elements in columns you\u2019d like to sort a table by, include ~1kB of JS \u0026amp; CSS, and initialise with \u003Ccode\u003Esorter()\u003C\/code\u003E \u2013 and that\u2019s it!\u003C\/p\u003E\n\u003Cp\u003EFor installation instructions and more customisation options, you can check out the \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Sorter\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E readme file\u003C\/a\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["html","javascript","js","library","lightweight","sort","sorting","table"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-sorter_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-sorter_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-sorter_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ELightweight sorting of tables.\u003C\/p\u003E\n\u003Cp\u003EJust add \u003Ccode\u003E[data-sort]\u003C\/code\u003E attributes to the \u003Ccode\u003Eth\u003C\/code\u003E elements in columns you\u2019d like to sort a table by, include ~1kB of JS \u0026amp; CSS, and initialise with \u003Ccode\u003Esorter()\u003C\/code\u003E \u2013 and that\u2019s it!\u003C\/p\u003E\n\u003Cp\u003EFor installation instructions and more customisation options, you can check out the \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Sorter\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E readme file\u003C\/a\u003E.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-sorter_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-sorter_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ELightweight sorting of tables.\u003C\/p\u003E\n\u003Cp\u003EJust add \u003Ccode\u003E[data-sort]\u003C\/code\u003E attributes to the \u003Ccode\u003Eth\u003C\/code\u003E elements in columns you\u2019d like to sort a table by, include ~1kB of JS \u0026amp; CSS, and initialise with \u003Ccode\u003Esorter()\u003C\/code\u003E \u2013 and that\u2019s it!\u003C\/p\u003E\n\u003Cp\u003EFor installation instructions and more customisation options, you can check out the \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Sorter\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E readme file\u003C\/a\u003E.\u003C\/p\u003E","words":50,"readTime":null,"lang":"en"}}},"projects\/columnist":{"key":"projects\/columnist","type":"article","published":true,"meta":{"createdAt":"2019-08-26T15:07:32+02:00","publishedAt":"2019-08-26T17:48:00+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/columnist.avris.it\/","displayUrl":"Demo"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Columnist","displayUrl":null},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/www.npmjs.com\/package\/avris-columnist","displayUrl":null}],"category":"projects","subcategory":null,"slug":"columnist"},"content":{"en":{"slug":"columnist","title":"Columnist \u2013 Simple and lightweight multi-column design","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.29473684211\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACMklEQVRIicWVQXPTMBCFv5WtNMRNmik\/iekU\/iX3\/hdOHGE40XOZkDSurF0OshzHiZ0OdIZ3sawn62mfdteiqkYPIoLZ0dSr599iTTkk+otjVB4ffxKaSOGEEBqiKqvVkpn3IML729uTzf8FMnSoj5fwQhMiaooTAQQA7z3en8TyJg6JnWNbbLdb6n1NVMV7T9SICGDJSTNwTpjNrri+ri5G\/xqUE+cBIDQNaoqaUlUVmLURCiLZsfJs1H+DSYf+B04ToYfPX+DhaxrfLiAq7AKECJ6aj80DALOZxzlHjJEQGgB+fP9GXe8pipLFYs5m8xuAT\/d33N996DTMrHMaBg4NyUvzfR7o1uT1\/e9eu6Y8J5jfVXU0N8aqJXOqOso550aDm8yh0DTkrrDdbqmqipTOqboy97zbIa5gPr+CHpfWGk9Pv1iv1x3ny\/FMmexDUZUx2okQNZ7nnEvukjvXMVcWxelBxjp1H6nXJOuf93vezecHThzJ26Gktd+mhtVmzpTMEcqpZG2VAdCo3ThDRLI+na5JulI5fxARGS0QEbncGE0Sv1gsunFWz\/Ef6UrmDggh4L1vN2SyiV50KMVrdP+M3gmS9nDeeodJv5fd7pmbmzLPTLaQySqLMRJHkrpwMso5EZp4vuyLYrrKJq9MzbC2WjabDavlsqscFdclfF3XFKWnLFJ\/MXHdhWYvDirj\/asNprV\/5IkIiLBcrtLuR8kqmAll6TEdFrkcHu0eTGjl8R8MrVmKlGbrrwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022488.58947368421\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACAElEQVRIiZVV207jMBA9M3ZWon0Csd\/B\/\/8E8MAPIMGudgtFglawJJ7ZB8d3h4ZRk9rj4zP2GTtDIqLT5ADCSSMQmAlO5DQYABNDoVDVVXhrDBgAnAhEtHh2u6fG50Qgqo3\/4\/0Du6d941cVSIf74eFX4\/N4hQ2rq3ex2WwbHxF1seM4YrvZdJTo47fbHnaeISI6ThMoz9nLi\/8\/P2\/4iQiTc4D6cIqUbU0wKAGWOSq6hCFNvh+D9QoNNgrl7XgAXl+Bn5fNDpyIZ4JGojqcYo6W2RImsXizIQ2FnZ0B+z3QG0PuDhoVo42vpenNmxfUzeXFBXA8Agt5Vsw6R72z\/IVAlCUz9yNvt\/x9heJGlsYo\/Pw5CPQd+GAt6hiqWvjyfl+hFDbeBiJK7RPfFapavRi1L\/S\/VggodhLbRPF65ZkhoLx21fw8+PcUensDDodFheI7HoXqUitiunP+guNbCj0+Avf3wNVVoxATwTKVMiRE0WPmRqGwqKXMkIjov8+xpFL1D3NDxobhJtclq80YA1GByrpaNgwWKSKFXRNAhNu7u9SfH+1hQXjeP+P3n78lnvJvTYm\/vrn1IxUPkCm0xogIxjCmlQpZk0rHGoulIwRbtSgAvBLrb+PyeelZUcT8Sfd3eRYw1ppQfJkZxpjm9qT55eY+RYpDnDC+vpGW1ew\/BCdqPrjZC2cAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022475.49103330487\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["column","design","javascript","layout","library","masonry","multi-column","npm"],"hasMore":true,"image":"https:\/\/avris.it\/image\/columnist_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.14736842105\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI like multi-column design. Unfortunately, it\u2019s really annoying to work with. If your tiles don\u2019t all have the same height, it looks awful.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why we have \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E (and \u003Ca href=\u0022https:\/\/alternativeto.net\/software\/masonry\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E alternatives\u003C\/a\u003E) \u2013 but they all use absolute positioning, which can be problematic for lazy loading of images, dynamically adding more elements, etc. We can \u003Ca href=\u0022https:\/\/tobiasahlin.com\/blog\/masonry-with-css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E try doing it with plain CSS\u003C\/a\u003E \u2013 alas, it either breaks the order of tiles or requires knowing the height of the container in advance.\u003C\/p\u003E\n\u003Cp\u003EBut I think I might have a solution to that: \u003Ca href=\u0022https:\/\/columnist.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DEMO\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ETake a look at this graphic:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/columnist-how_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/columnist-how_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022118.87275832622\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EOur main job is to make the empty space marked with the red arrow disappear. If we can calculate its height, we can give the tile right below it a negative \u003Ccode\u003Emargin-top\u003C\/code\u003E to compensate for the height of the empty space.\u003C\/p\u003E\n\u003Cp\u003EAnd we can! All we need is to make sure that the column only has one child element. The difference between the height of the column and of that child is what we need to compensate for.\u003C\/p\u003E\n\u003Cp\u003EWe can find the tile right below from it (\u003Ccode\u003Ei + numberOfColumns\u003C\/code\u003E), give it \u003Ccode\u003Emargin-top: -${diff}px\u003C\/code\u003E et voil\u00e0!\u003C\/p\u003E\n\u003Ch3\u003ELimitations\u003C\/h3\u003E\n\u003Cp\u003EMy script does not do any maths fancier than this. If your first column contains a very tall tile A and a small tile B, and your second column only contains a small tile C, it would look nicer, if B were moved to the second column. My script doesn\u2019t do that. That\u2019s the price of simplicity.\u003C\/p\u003E\n\u003Ch3\u003EFuture work\u003C\/h3\u003E\n\u003Cp\u003ECurrent implementation relies a \u003Ccode\u003EsetInterval\u003C\/code\u003E that reapplies the layout every 300 ms. Firstly, because a couple of iterations are needed to get the final layout, and secondly, because the DOM and window can change.\u003C\/p\u003E\n\u003Cp\u003EObviously, I can get rid of both those problems. Applying the layout in a loop or in some smarter way, adding event listeners, etc.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s a job for the next free evening \/ weekend.\u003C\/p\u003E\n\u003Cp\u003EAnyways, check out the links below and enjoy \ud83d\ude09\u003C\/p\u003E","words":331,"readTime":2,"lang":"en"}}},"projects\/vanillin":{"key":"projects\/vanillin","type":"article","published":true,"meta":{"createdAt":"2018-02-10T22:05:06+01:00","publishedAt":"2018-02-10T22:03:00+01:00","group":"vanillin","links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/www.npmjs.com\/package\/avris-vanillin","displayUrl":"npm: avris-vanillin"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Vanillin","displayUrl":null}],"category":"projects","subcategory":null,"slug":"vanillin"},"content":{"en":{"slug":"vanillin","title":"Vanillin \u2013 Almost like vanilla JavaScript","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/vanillin_small.png\u0022 alt=\u0022Vanillin.js\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022269.94727592267\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADvElEQVRIie2VXUxbZRjHf+05W6nAYGXyjXQQBwlpJpQLGwxZIioGF73QeGMiMSaGRA3BmV15YbhYxAuucLvQxCySJYZENgwKk5oomYUOSIflK5J+WAqF5qwttKctpz1eWBAZSxZDvdo\/eXPe\/J8n7\/N7P877wmP9B83Pzz8zPT39bnt7+4vOmpp+f23t+qzRaL9WVtac7driYWN2dva5qqqqn3t7e0WDwUCiuJhSQaBQkkpXUqnvns\/NPTsRjSrZAtIeNhRFeXloaEjc3t6mtbWVqYYG0GpJqioyVAqiaMgWzJFANpvt5vj4eDKVSiHLMo4TJ\/g+HOY3Wcaxu3tXCoc3\/xeg1dXVdo\/HY19cXPw8Ho\/vCILAxsYGoVCIr8vKKLp6lS6rNe\/D69efzSaQCNDd3S0WFBTcGBgYKEylUpSXl1NcXExlZSWRSARtURHeWIzXzp2rX1he\/gpoeISxtUCaf85pOtOOyvk3UCwWY2JiQlxYWKClpYWcnBwmJydxu900NTWRm5vL6OgoJpMJt9t9cLBPgSvA+8A3wCaQl4m3AaeACPACsAhcAwqBDaAUuACMA3EgBiAAzMzMpGVZTgiC8FIymWR9fZ1AIICiKMiyjN\/vJxAI8NPt27GNQOBNp9PpBVTgdeAs4AI+AFqBtzP+\/cyEt4Fa4EnAnImFgJ1M\/hXADqztA42MjDyh0+k+iUQiNRaLhWQySTQaRa\/X09jYiCiKvOJw0Ol2a8rcbvG0VvuDPR5PAT6gDxgA3gCimUL3MyASYATqM34UuMvfW14C5APhTP+X\/S2rrq5+p7m5ua2np4elpSUkScJiseDz+YhEItT6fHSk01BUJMrBYGeJXm8nFPoCuAeYgCTwauZ7UGke\/JP3vE7ABsxmVox9IJfLRUVFBWazGavVisFgYHd3F0VRsNvt5IfDfHvmDClVJZFIIMXjTx8osAcR42gdPsh73pdHJQsAer3+XiAQMMZisbzTd+7IHwWD+TUuF6LXy1MdHbzV10eivh5rMMif5eVcvHw52WQ2\/zg2NrbzEIjj04zR+Gvq\/Hk13damBk0mVdraUtPptCrLstrf369OTU2p8XhcHRwcvJGN+g\/c1CuKsuLZ2WHL62UhGuX3uTlCoRDLy8s4HA7q6uqQJAm\/35+VJ0Q4bJScPGnzqGqjQ1GM2y0tGoxGbt66xfDwMC6XC41Gg81m887NzXU5nc614wbSPCzw8aVLF04VFHT5fD6nTqebXFtbe8\/j8fzh9Xo\/29zcjBw3yGM9qv4CsPqrHrao4OAAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/vanillin_small.png\u0022 alt=\u0022Vanillin.js\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022269.94727592267\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EjQuery used to be virtually indispensable,\nif you wanted to develop a cross-browser website without getting a headache.\u003C\/p\u003E\n\u003Cp\u003EToday, however, you might not need jQuery,\nespecially, if you\u2019re developing a library and want to avoid unnecessary dependencies.\u003C\/p\u003E\n\u003Cp\u003EStill, some helpers could be useful...\nVanillin is an opinionated set of helpers\nthat I find most useful, a bare minimum to make life easier.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/vanillin_big.png\u0022 alt=\u0022Vanillin.js\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022539.89455184534\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADvElEQVRIie2VXUxbZRjHf+05W6nAYGXyjXQQBwlpJpQLGwxZIioGF73QeGMiMSaGRA3BmV15YbhYxAuucLvQxCySJYZENgwKk5oomYUOSIflK5J+WAqF5qwttKctpz1eWBAZSxZDvdo\/eXPe\/J8n7\/N7P877wmP9B83Pzz8zPT39bnt7+4vOmpp+f23t+qzRaL9WVtac7driYWN2dva5qqqqn3t7e0WDwUCiuJhSQaBQkkpXUqnvns\/NPTsRjSrZAtIeNhRFeXloaEjc3t6mtbWVqYYG0GpJqioyVAqiaMgWzJFANpvt5vj4eDKVSiHLMo4TJ\/g+HOY3Wcaxu3tXCoc3\/xeg1dXVdo\/HY19cXPw8Ho\/vCILAxsYGoVCIr8vKKLp6lS6rNe\/D69efzSaQCNDd3S0WFBTcGBgYKEylUpSXl1NcXExlZSWRSARtURHeWIzXzp2rX1he\/gpoeISxtUCaf85pOtOOyvk3UCwWY2JiQlxYWKClpYWcnBwmJydxu900NTWRm5vL6OgoJpMJt9t9cLBPgSvA+8A3wCaQl4m3AaeACPACsAhcAwqBDaAUuACMA3EgBiAAzMzMpGVZTgiC8FIymWR9fZ1AIICiKMiyjN\/vJxAI8NPt27GNQOBNp9PpBVTgdeAs4AI+AFqBtzP+\/cyEt4Fa4EnAnImFgJ1M\/hXADqztA42MjDyh0+k+iUQiNRaLhWQySTQaRa\/X09jYiCiKvOJw0Ol2a8rcbvG0VvuDPR5PAT6gDxgA3gCimUL3MyASYATqM34UuMvfW14C5APhTP+X\/S2rrq5+p7m5ua2np4elpSUkScJiseDz+YhEItT6fHSk01BUJMrBYGeJXm8nFPoCuAeYgCTwauZ7UGke\/JP3vE7ABsxmVox9IJfLRUVFBWazGavVisFgYHd3F0VRsNvt5IfDfHvmDClVJZFIIMXjTx8osAcR42gdPsh73pdHJQsAer3+XiAQMMZisbzTd+7IHwWD+TUuF6LXy1MdHbzV10eivh5rMMif5eVcvHw52WQ2\/zg2NrbzEIjj04zR+Gvq\/Hk13damBk0mVdraUtPptCrLstrf369OTU2p8XhcHRwcvJGN+g\/c1CuKsuLZ2WHL62UhGuX3uTlCoRDLy8s4HA7q6uqQJAm\/35+VJ0Q4bJScPGnzqGqjQ1GM2y0tGoxGbt66xfDwMC6XC41Gg81m887NzXU5nc614wbSPCzw8aVLF04VFHT5fD6nTqebXFtbe8\/j8fzh9Xo\/29zcjBw3yGM9qv4CsPqrHrao4OAAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/vanillin_big.png\u0022 alt=\u0022Vanillin.js\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022539.89455184534\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Vanillin#\/media\/File:Vanillin-3d.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        en.wikipedia.org\/wiki\/Vanillin#\/media\/File:Vanillin-3d.png\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EjQuery used to be virtually indispensable,\nif you wanted to develop a cross-browser website without getting a headache.\u003C\/p\u003E\n\u003Cp\u003EToday, however, you might not need jQuery,\nespecially, if you\u2019re developing a library and want to avoid unnecessary dependencies.\u003C\/p\u003E\n\u003Cp\u003EStill, some helpers could be useful...\nVanillin is an opinionated set of helpers\nthat I find most useful, a bare minimum to make life easier.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["helper","javascript","js","library","programming","vanilla"],"hasMore":false,"image":"https:\/\/avris.it\/image\/vanillin_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/vanillin_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/vanillin_mini.png\u0022 alt=\u0022Vanillin.js\u0022 width=\u0022240\u0022 height=\u0022134.97363796134\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EjQuery used to be virtually indispensable,\nif you wanted to develop a cross-browser website without getting a headache.\u003C\/p\u003E\n\u003Cp\u003EToday, however, you might not need jQuery,\nespecially, if you\u2019re developing a library and want to avoid unnecessary dependencies.\u003C\/p\u003E\n\u003Cp\u003EStill, some helpers could be useful...\nVanillin is an opinionated set of helpers\nthat I find most useful, a bare minimum to make life easier.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/vanillin_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/vanillin_mini.png\u0022 alt=\u0022Vanillin.js\u0022 width=\u0022240\u0022 height=\u0022134.97363796134\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Vanillin#\/media\/File:Vanillin-3d.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Een.wikipedia.org\/wiki\/Vanillin#\/media\/File:Vanillin-3d.png\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EjQuery used to be virtually indispensable,\nif you wanted to develop a cross-browser website without getting a headache.\u003C\/p\u003E\n\u003Cp\u003EToday, however, you might not need jQuery,\nespecially, if you\u2019re developing a library and want to avoid unnecessary dependencies.\u003C\/p\u003E\n\u003Cp\u003EStill, some helpers could be useful...\nVanillin is an opinionated set of helpers\nthat I find most useful, a bare minimum to make life easier.\u003C\/p\u003E","words":73,"readTime":null,"lang":"en"}}},"projects\/avris-forms":{"key":"projects\/avris-forms","type":"article","published":true,"meta":{"createdAt":"2018-01-26T20:28:10+01:00","publishedAt":"2018-01-26T20:27:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Forms","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-forms"},"content":{"en":{"slug":"avris-forms","title":"Avris Forms","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHk0lEQVRIiX2X268lRRXGf+tS1b33PnufM8PMgWGA4SaKqEQikYQQkASBGDRovKAJ0Qd90Pjgn+C7bz4Yjc\/6ZHxBTDQagQQSReMFEIngzHAZEOZyztnnsnd31fKh9wxGjZWu7k66Ll99X61aX8s1194SUSpCELVCVMydWgpBoCK4GqZKcme5XFBrhQiIQAARQRiKiCAiQHCxRMSq1ktPoiICKoK5YyI0zQiPECKCUgsSIEApBWEYWFUHoKJQK0mVfjUBIqt2XGovAiCoyruTy8V3IWpB1Ih4t58hJDW0FvxiB0EJKhGgIYgOkxGCqgNCXyqGoAghiqmu2BgWggzfVtfqZrgby2WHCEQMCxRRdNXXVHEzkioeolDLiuCBESKQEFQNN8VEMFHcFIlKrZVayzCA+7D6WlG1S1KpCFErQbC+scGFc+eBCiGIQ9SCqkCAmZLMSH4RkAAqUFdsCYjoSgZDUcyMbIlx00D07O3v07jTJCd7otZKKT19KSAM+6VWAI5dvsliZw7UgbQIVPMKlGI6SJxNcdFERIeEgVT00iYV1Gyg1hIqioqh4kyaCYdG65yfb6GhRAkaT6hniEKI0PfdwJDAiWuu4c2TpxEJJMBUEAJIiMRKMiWZ4poyfbCKGLsYK6A6sKOGqZHdyZZQDJFEkxPXHV1jd2\/Oouu4\/IpNlvt7zLd3MBGyKzUqd378bl5+4UVmuSGIIbIA1UEUVRCBZEp2w0MTklZyIdQAE0XVUFHcHFcje8ZFSOYkSSRtOHx4nU9\/+bMcPrTBb37yc1499SrWrJF8iKbp+hp33ns3zz\/xNBvtCChExABGBRUwE0wH1twFJzdI79QaK30BFFFDzREx3BzVhJutauKeB+\/ikW98npee\/SuPfffHJAo3HbuSqJWd3TmejS99+1s8+9PHuWo2Y1k6avRElEE6XUVXGvZQToopuLQTaleQWodzKAAxRBy1RDJH1UjmtCkzducrX\/8M9z98D\/PzOzz+\/cfIOuLQuOWGG69kd+sdtvYOuPebXySpUE+9xvuObTLf3+OgX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjk0fu4\/+F7APjzU8+RaJiuTVkbN+yc2+fERz7Exx+6E28bnvnOD9k8so5Gx9Z20PeJEgOgkIpqkLLjLqSkeBZcRlPIPRSQUAhFUBAHTZg6yZycErfeeh2f\/NzHLqWE7bfmXHb5UY6f2OTELVdz9W3XMzkyIyJ49RdPMhllSl2jbXpyU0EqNTr6fknUDjVQDcyN3DieBGe6Dn0hQgYwMUSX4bgmFEdWB+CjX3vw0skM8MBX7+M\/S0Tw+pO\/Z\/n2Oxy99jIWW5lu9wIz7RCriAW1dtR+gdCjJpgrKWe8aXCdTkmFIc+geCgJI4uTw8hqZJTbbr2G48cP\/xeAfy+1FF7+5e\/Yeell2onSro85evNV9FsTts8IKkuEDiQTJSFShwhLjuWMNSN8ujGlFGDFkCF4OK0YLUqL0VThjo\/e+H\/BzN\/e4oWfPc3y7NuMGkCh299j72yHy5LxekPtynD2GKgkZCWXumO5RZsRfsXhEX0f1AI1FA1FMVIICaMNpSnCTdcf+Z9A9rf3+NtTz\/H6H14kS8eorUPqqBAd1IVBo+SREkkxiZVMCTXFUkZzg6QG8gj\/wGbD3kHHclFY9pVSKqVWJASJihXBRDhyaHwJxO58n1Mvvc7JP73C68\/\/gyY6xl6IVHAqWSuhARawHHKlpCB54CaYCZoSkltIBjlDbsBb\/KFDb7B7UJnPO7Z3K\/M+2FnA3hIOOlj2QunhB9\/7Efu7+1x4Z5vdc9vkUkgUEpVWKyPrmaRg1laW4wrTIIXQ2mAzpHSoB5YNq0HXGcaUbmFom9g6P6ajRe655UjM2sTBwWCV3DIhTsUJSRScqpm+QoiCOiLKxmydyXjMztYW2YxsQqMwyTDNcHQSHDtU2DxiTCbC6TMXmO\/vU3LHxpXHeeJXv+XkmQWztrK5OWXRBc+8sIusbRwOTRlRw1LCmxZRw3ODp4ylBlUjNy3mieQZt8Rdd9xOt79gbTyiWxYmueXoxoTFzpxzp99gTM9GC5etKYcmkLQnWc\/GpOemW8dcODPn7TPbTEfg0nP0jvvY+8uv8Zs\/9QWatRl9hXYyxVODqiPmJE+IGMKQdyQEKRVKYTGbMmePzWNHOHt2i3mFRAttIh8fsdies3BhNyk5GW2qVKscNJXONjj8Xrgwf4U0Ehrv6c\/vsfb++\/GCMd\/bB0ssd3YQ2QV08EIxGPDBC7ECU5Fa+efpA6iFV08aUgKJwGohMXjjccpMkzN1Z71JjJPgWhhnmB903P7BGa+dV+q5ntkIphfe4D0PfBg\/f+rvLLsO9UwtFW9G8O4\/BAJ4SqgqEkHUQGMAoLUifX\/J4NdugYtx4a3TtLnFRVhfm3HZbAOPyt7eNodmU\/74ovPmqRFvbR1w8uwBoxw0uuQT\/WvIkRtujloK\/XJJ7RakyRQJoSwP0NQM6aD2eG4BBs8NaA0UQeKihx68uEYgVEwEV8EFlEo2QzXo+w6hsDl11lvj3P5gcxuHO07AvwDs3DcxrBe3EwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-forms_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EForms are complicated. There are many things you must take into consideration:\nbinding an existing object (if any) to each sparate field of the form,\nvalidating them after user has submited the form,\nif invalid redisplaying it with POST data bound and with validation errors,\nbinding the data back to an object...\u003C\/p\u003E\n\u003Cp\u003EAvris Forms add an abstraction layer that handles all of that.\nYou just need to define the list of fields you need and their cofiguration options.\nYou\u2019ll get an object that will handle everything for you.\nJust handle it in the controller and display it in the view.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHk0lEQVRIiX2X268lRRXGf+tS1b33PnufM8PMgWGA4SaKqEQikYQQkASBGDRovKAJ0Qd90Pjgn+C7bz4Yjc\/6ZHxBTDQagQQSReMFEIngzHAZEOZyztnnsnd31fKh9wxGjZWu7k66Ll99X61aX8s1194SUSpCELVCVMydWgpBoCK4GqZKcme5XFBrhQiIQAARQRiKiCAiQHCxRMSq1ktPoiICKoK5YyI0zQiPECKCUgsSIEApBWEYWFUHoKJQK0mVfjUBIqt2XGovAiCoyruTy8V3IWpB1Ih4t58hJDW0FvxiB0EJKhGgIYgOkxGCqgNCXyqGoAghiqmu2BgWggzfVtfqZrgby2WHCEQMCxRRdNXXVHEzkioeolDLiuCBESKQEFQNN8VEMFHcFIlKrZVayzCA+7D6WlG1S1KpCFErQbC+scGFc+eBCiGIQ9SCqkCAmZLMSH4RkAAqUFdsCYjoSgZDUcyMbIlx00D07O3v07jTJCd7otZKKT19KSAM+6VWAI5dvsliZw7UgbQIVPMKlGI6SJxNcdFERIeEgVT00iYV1Gyg1hIqioqh4kyaCYdG65yfb6GhRAkaT6hniEKI0PfdwJDAiWuu4c2TpxEJJMBUEAJIiMRKMiWZ4poyfbCKGLsYK6A6sKOGqZHdyZZQDJFEkxPXHV1jd2\/Oouu4\/IpNlvt7zLd3MBGyKzUqd378bl5+4UVmuSGIIbIA1UEUVRCBZEp2w0MTklZyIdQAE0XVUFHcHFcje8ZFSOYkSSRtOHx4nU9\/+bMcPrTBb37yc1499SrWrJF8iKbp+hp33ns3zz\/xNBvtCChExABGBRUwE0wH1twFJzdI79QaK30BFFFDzREx3BzVhJutauKeB+\/ikW98npee\/SuPfffHJAo3HbuSqJWd3TmejS99+1s8+9PHuWo2Y1k6avRElEE6XUVXGvZQToopuLQTaleQWodzKAAxRBy1RDJH1UjmtCkzducrX\/8M9z98D\/PzOzz+\/cfIOuLQuOWGG69kd+sdtvYOuPebXySpUE+9xvuObTLf3+OgX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjk0fu4\/+F7APjzU8+RaJiuTVkbN+yc2+fERz7Exx+6E28bnvnOD9k8so5Gx9Z20PeJEgOgkIpqkLLjLqSkeBZcRlPIPRSQUAhFUBAHTZg6yZycErfeeh2f\/NzHLqWE7bfmXHb5UY6f2OTELVdz9W3XMzkyIyJ49RdPMhllSl2jbXpyU0EqNTr6fknUDjVQDcyN3DieBGe6Dn0hQgYwMUSX4bgmFEdWB+CjX3vw0skM8MBX7+M\/S0Tw+pO\/Z\/n2Oxy99jIWW5lu9wIz7RCriAW1dtR+gdCjJpgrKWe8aXCdTkmFIc+geCgJI4uTw8hqZJTbbr2G48cP\/xeAfy+1FF7+5e\/Yeell2onSro85evNV9FsTts8IKkuEDiQTJSFShwhLjuWMNSN8ujGlFGDFkCF4OK0YLUqL0VThjo\/e+H\/BzN\/e4oWfPc3y7NuMGkCh299j72yHy5LxekPtynD2GKgkZCWXumO5RZsRfsXhEX0f1AI1FA1FMVIICaMNpSnCTdcf+Z9A9rf3+NtTz\/H6H14kS8eorUPqqBAd1IVBo+SREkkxiZVMCTXFUkZzg6QG8gj\/wGbD3kHHclFY9pVSKqVWJASJihXBRDhyaHwJxO58n1Mvvc7JP73C68\/\/gyY6xl6IVHAqWSuhARawHHKlpCB54CaYCZoSkltIBjlDbsBb\/KFDb7B7UJnPO7Z3K\/M+2FnA3hIOOlj2QunhB9\/7Efu7+1x4Z5vdc9vkUkgUEpVWKyPrmaRg1laW4wrTIIXQ2mAzpHSoB5YNq0HXGcaUbmFom9g6P6ajRe655UjM2sTBwWCV3DIhTsUJSRScqpm+QoiCOiLKxmydyXjMztYW2YxsQqMwyTDNcHQSHDtU2DxiTCbC6TMXmO\/vU3LHxpXHeeJXv+XkmQWztrK5OWXRBc+8sIusbRwOTRlRw1LCmxZRw3ODp4ylBlUjNy3mieQZt8Rdd9xOt79gbTyiWxYmueXoxoTFzpxzp99gTM9GC5etKYcmkLQnWc\/GpOemW8dcODPn7TPbTEfg0nP0jvvY+8uv8Zs\/9QWatRl9hXYyxVODqiPmJE+IGMKQdyQEKRVKYTGbMmePzWNHOHt2i3mFRAttIh8fsdies3BhNyk5GW2qVKscNJXONjj8Xrgwf4U0Ehrv6c\/vsfb++\/GCMd\/bB0ssd3YQ2QV08EIxGPDBC7ECU5Fa+efpA6iFV08aUgKJwGohMXjjccpMkzN1Z71JjJPgWhhnmB903P7BGa+dV+q5ntkIphfe4D0PfBg\/f+rvLLsO9UwtFW9G8O4\/BAJ4SqgqEkHUQGMAoLUifX\/J4NdugYtx4a3TtLnFRVhfm3HZbAOPyt7eNodmU\/74ovPmqRFvbR1w8uwBoxw0uuQT\/WvIkRtujloK\/XJJ7RakyRQJoSwP0NQM6aD2eG4BBs8NaA0UQeKihx68uEYgVEwEV8EFlEo2QzXo+w6hsDl11lvj3P5gcxuHO07AvwDs3DcxrBe3EwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-forms_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EForms are complicated. There are many things you must take into consideration:\nbinding an existing object (if any) to each sparate field of the form,\nvalidating them after user has submited the form,\nif invalid redisplaying it with POST data bound and with validation errors,\nbinding the data back to an object...\u003C\/p\u003E\n\u003Cp\u003EAvris Forms add an abstraction layer that handles all of that.\nYou just need to define the list of fields you need and their cofiguration options.\nYou\u2019ll get an object that will handle everything for you.\nJust handle it in the controller and display it in the view.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["abstraction","forms","library","php"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-forms_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-forms_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EForms are complicated. There are many things you must take into consideration:\nbinding an existing object (if any) to each sparate field of the form,\nvalidating them after user has submited the form,\nif invalid redisplaying it with POST data bound and with validation errors,\nbinding the data back to an object...\u003C\/p\u003E\n\u003Cp\u003EAvris Forms add an abstraction layer that handles all of that.\nYou just need to define the list of fields you need and their cofiguration options.\nYou\u2019ll get an object that will handle everything for you.\nJust handle it in the controller and display it in the view.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-forms_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EForms are complicated. There are many things you must take into consideration:\nbinding an existing object (if any) to each sparate field of the form,\nvalidating them after user has submited the form,\nif invalid redisplaying it with POST data bound and with validation errors,\nbinding the data back to an object...\u003C\/p\u003E\n\u003Cp\u003EAvris Forms add an abstraction layer that handles all of that.\nYou just need to define the list of fields you need and their cofiguration options.\nYou\u2019ll get an object that will handle everything for you.\nJust handle it in the controller and display it in the view.\u003C\/p\u003E","words":101,"readTime":null,"lang":"en"}}},"projects\/avris-http":{"key":"projects\/avris-http","type":"article","published":true,"meta":{"createdAt":"2018-01-12T20:41:21+01:00","publishedAt":"2018-01-12T20:40:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Http","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-http"},"content":{"en":{"slug":"avris-http","title":"Avris Http","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-http_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHiklEQVRIiX2Xy69lRRXGf+tRtfc55577aLovb5qXKKJ0RI0kxIAkvGLQoPGBJkQHOtA48E9w7syB0TjWkXGCmGg0AgkkisYHIBJBGmga0tD3de659569q5aDfboxaqzsV7Krdn31fWvV+rZcc+0tEaUiBFErRMXcqaUQBCqCq2GqJHcWiyNqrRABEQggIghDExFEBAgutIhYnvXinaiIgIpg7pgITTPCI4SIoNSCBAhQSkEYPqyqA1BRqJWkSr+cAJFlPy72FwEQVOXdyeXCsxC1IGpEvDvOEJIaWgt+YYCgBJUI0BBEh8kIQdUBoS8VQ1CEEMVUl2wMC0GGd8tjeTHcjcWiQwQihgWKKLoca6q4GUkVD1GoZUnwwAgRSAiqhptiIpgobopEpdZKrWX4gPuw+lpRtYtSqQhRK0Gwtr7O9vktoEII4hC1oCoQYKYkM5JfACSACtQlWwIiupTBUBQzI1ti3DQQPfODAxp3muRkT9RaKaWnLwWEIV5qBeDySzc52psBdSAtAtW8BKWYDhJnU1w0EdEhYSAVvRikgpoN1FpCRVExVJxJM2FjtMbWbAcNJUrQeEI9QxRChL7vBoYETl5zDW++8ioigQSYCkIACZFYSqYkU1xTpg+WGWMXcgVUB3bUMDWyO9kSiiGSaHLiuhMr7M9nHHUdl162yeJgzmx3DxMhu1Kjcse9d\/LS8y+wmhuCGDILUB1EUQURSKZkNzw0IWkpF0INMFFUDRXFzXE1smdchGROkkTShmPH1vjMVz7HsY11fvvTX\/Da6dewZoXkQzZN11a44+47ee7xp1hvR0AhIgYwKqiAmWA6sOYuOLlBeqfWWOoLoIgaao6I4eaoJtxseSbueuDjPPzNL\/DiM3\/j0e\/9hEThpsuvIGplb3+GZ+PL3\/k2z\/zsMa5aXWVROmr0RJRBOl1mVxpiKCfFFFzaCbUrSK3DPhSAGCKOWiKZo2okc9qUGbvz1W98lvseuovZ1h6P\/eBRso7YGLfccOMV7O+8zc78kLu\/9SWSCvX067zv8k1mB3MO+wWl9pTagVaSG2aCu5JcSMlwGa8iix5KJWCIERSRhIohnsjqtCkxTomHH7mH+x66C4C\/PPksiYbpypSVccPe+QNOfuRW7n3wDrxtePq7P2Lz+BoaHTu7Qd8nSgyAQiqqQcqOu5CS4llwGU0h91BAQiEUQUEcNGHqJHNySpw6dR2f+vwnLpaE3bdmXHLpCa48ucnJW67m6tuuZ3J8lYjgtV8+wWSUKXWFtunJTQWp1Ojo+wVRO9RANTA3cuN4EpzpGvSFCBnAxJBdhuOaUBxZboCPfP2BizszwP1fu4f\/bBHBmSf+wOLc25y49hKOdjLd\/jar2iFWEQtq7aj9EUKPmmCupJzxpsF1OiUVhjqD4qEkjCxODiOrkVFuO3UNV1557L8A\/HurpfDSr37P3osv0U6Udm3MiZuvot+ZsHtWUFkgdCCZKAmROmRYcixnrBnh0\/UppQBLhgzBw2nFaFFajKYKt3\/sxv8LZnZuh+d\/\/hSLd84xagCF7mDO\/J0OlwXjtYbalWHvMVBJyFIudcdyizYj\/LJjI\/o+qAVqKBqKYqQQEkYbSlOEm64\/\/j+BHOzO+fuTz3Lmjy+QpWPU1qF0VIgO6pFBo+SREkkxiaVMCTXFUkZzg6QG8gj\/wGbD\/LBjcVRY9JVSKqVWJASJihXBRDi+Mb4IYn92wOkXz\/DKn1\/mzHP\/pImOsRciFZxK1kpogAUshlopKUgeuAlmgqaE5BaSQc6QG\/AWf3DjDfYPK7NZx+5+ZdYHe0cwX8BhB4teKD388Ps\/5mD\/gO23d9k\/v0suhUQhUWm1MrKeSQpW28piXGEapBBaG2yGlA71wLJhNeg6w5jSHRnaJna2xnS0yF23HI\/VNnF4OFglt0yIU3FCEgWnaqavEKKgjojiakzGY7IZCmQTPAqTDNMMJybB5RuFzePGZCK8enab2cEBJXesX3Elj\/\/6d7xy9ojVtrK5OeWoC55+fh9ZWT8WmjKihqWENy2ihucGTxlLDapGblrME8kzbommGXHHh29lbWUFFSOLsb+9w8HWNoutHTZaZb2FS1aUjQkk7UnWsz7puenUmO2zM86d3WU6ApeeE7ffw\/yvv8Fv\/vQXaVZW6Su0kymeGlQdMSd5QsQQhrojIUipUApSg\/loynxRWBtlLIRLr72e1+RNelnhyJQjF\/aTkpPRpkq1ymFT6WydY++F7dnLpJHQeE+\/NWfl\/ffhBWM2PwBLLPb2ENkHdPBCMRjwwQuxBFORWqmHh7z1aiGbISWQCDwCD0FrYZwy0+RM3VlrEuMkuBbGGWaHHR\/94Cqvbyn1fM\/qCKbbb\/Ce+z+Eb53+B4uuQz1TS8WbEbz7D4EAnhKqikQQNdAYAGitSN9fNPi1O8LF2H7rVdrc4iKsraxyyeo6HpX5fJeN1Sl\/esF58\/SIt3YOeeWdQ0Y5aHTBJ\/vXkeM33By1FPrFgtodkSZTJISyOERTM5SD2uO5BRg8N6A1UASJCx568OIagVAxEVwFF1DqEPwa9H2HUNicOmutcf5gsLmNw+0n4V\/6+DKRylDp2gAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-http_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHTTP Request\/Response abstraction\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-http_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHiklEQVRIiX2Xy69lRRXGf+tRtfc55577aLovb5qXKKJ0RI0kxIAkvGLQoPGBJkQHOtA48E9w7syB0TjWkXGCmGg0AgkkisYHIBJBGmga0tD3de659569q5aDfboxaqzsV7Krdn31fWvV+rZcc+0tEaUiBFErRMXcqaUQBCqCq2GqJHcWiyNqrRABEQggIghDExFEBAgutIhYnvXinaiIgIpg7pgITTPCI4SIoNSCBAhQSkEYPqyqA1BRqJWkSr+cAJFlPy72FwEQVOXdyeXCsxC1IGpEvDvOEJIaWgt+YYCgBJUI0BBEh8kIQdUBoS8VQ1CEEMVUl2wMC0GGd8tjeTHcjcWiQwQihgWKKLoca6q4GUkVD1GoZUnwwAgRSAiqhptiIpgobopEpdZKrWX4gPuw+lpRtYtSqQhRK0Gwtr7O9vktoEII4hC1oCoQYKYkM5JfACSACtQlWwIiupTBUBQzI1ti3DQQPfODAxp3muRkT9RaKaWnLwWEIV5qBeDySzc52psBdSAtAtW8BKWYDhJnU1w0EdEhYSAVvRikgpoN1FpCRVExVJxJM2FjtMbWbAcNJUrQeEI9QxRChL7vBoYETl5zDW++8ioigQSYCkIACZFYSqYkU1xTpg+WGWMXcgVUB3bUMDWyO9kSiiGSaHLiuhMr7M9nHHUdl162yeJgzmx3DxMhu1Kjcse9d\/LS8y+wmhuCGDILUB1EUQURSKZkNzw0IWkpF0INMFFUDRXFzXE1smdchGROkkTShmPH1vjMVz7HsY11fvvTX\/Da6dewZoXkQzZN11a44+47ee7xp1hvR0AhIgYwKqiAmWA6sOYuOLlBeqfWWOoLoIgaao6I4eaoJtxseSbueuDjPPzNL\/DiM3\/j0e\/9hEThpsuvIGplb3+GZ+PL3\/k2z\/zsMa5aXWVROmr0RJRBOl1mVxpiKCfFFFzaCbUrSK3DPhSAGCKOWiKZo2okc9qUGbvz1W98lvseuovZ1h6P\/eBRso7YGLfccOMV7O+8zc78kLu\/9SWSCvX067zv8k1mB3MO+wWl9pTagVaSG2aCu5JcSMlwGa8iix5KJWCIERSRhIohnsjqtCkxTomHH7mH+x66C4C\/PPksiYbpypSVccPe+QNOfuRW7n3wDrxtePq7P2Lz+BoaHTu7Qd8nSgyAQiqqQcqOu5CS4llwGU0h91BAQiEUQUEcNGHqJHNySpw6dR2f+vwnLpaE3bdmXHLpCa48ucnJW67m6tuuZ3J8lYjgtV8+wWSUKXWFtunJTQWp1Ojo+wVRO9RANTA3cuN4EpzpGvSFCBnAxJBdhuOaUBxZboCPfP2BizszwP1fu4f\/bBHBmSf+wOLc25y49hKOdjLd\/jar2iFWEQtq7aj9EUKPmmCupJzxpsF1OiUVhjqD4qEkjCxODiOrkVFuO3UNV1557L8A\/HurpfDSr37P3osv0U6Udm3MiZuvot+ZsHtWUFkgdCCZKAmROmRYcixnrBnh0\/UppQBLhgzBw2nFaFFajKYKt3\/sxv8LZnZuh+d\/\/hSLd84xagCF7mDO\/J0OlwXjtYbalWHvMVBJyFIudcdyizYj\/LJjI\/o+qAVqKBqKYqQQEkYbSlOEm64\/\/j+BHOzO+fuTz3Lmjy+QpWPU1qF0VIgO6pFBo+SREkkxiaVMCTXFUkZzg6QG8gj\/wGbD\/LBjcVRY9JVSKqVWJASJihXBRDi+Mb4IYn92wOkXz\/DKn1\/mzHP\/pImOsRciFZxK1kpogAUshlopKUgeuAlmgqaE5BaSQc6QG\/AWf3DjDfYPK7NZx+5+ZdYHe0cwX8BhB4teKD388Ps\/5mD\/gO23d9k\/v0suhUQhUWm1MrKeSQpW28piXGEapBBaG2yGlA71wLJhNeg6w5jSHRnaJna2xnS0yF23HI\/VNnF4OFglt0yIU3FCEgWnaqavEKKgjojiakzGY7IZCmQTPAqTDNMMJybB5RuFzePGZCK8enab2cEBJXesX3Elj\/\/6d7xy9ojVtrK5OeWoC55+fh9ZWT8WmjKihqWENy2ihucGTxlLDapGblrME8kzbommGXHHh29lbWUFFSOLsb+9w8HWNoutHTZaZb2FS1aUjQkk7UnWsz7puenUmO2zM86d3WU6ApeeE7ffw\/yvv8Fv\/vQXaVZW6Su0kymeGlQdMSd5QsQQhrojIUipUApSg\/loynxRWBtlLIRLr72e1+RNelnhyJQjF\/aTkpPRpkq1ymFT6WydY++F7dnLpJHQeE+\/NWfl\/ffhBWM2PwBLLPb2ENkHdPBCMRjwwQuxBFORWqmHh7z1aiGbISWQCDwCD0FrYZwy0+RM3VlrEuMkuBbGGWaHHR\/94Cqvbyn1fM\/qCKbbb\/Ce+z+Eb53+B4uuQz1TS8WbEbz7D4EAnhKqikQQNdAYAGitSN9fNPi1O8LF2H7rVdrc4iKsraxyyeo6HpX5fJeN1Sl\/esF58\/SIt3YOeeWdQ0Y5aHTBJ\/vXkeM33By1FPrFgtodkSZTJISyOERTM5SD2uO5BRg8N6A1UASJCx568OIagVAxEVwFF1DqEPwa9H2HUNicOmutcf5gsLmNw+0n4V\/6+DKRylDp2gAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-http_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHTTP Request\/Response abstraction\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["abstraction","http","library","php","request","response","session"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-http_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-http_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-http_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHTTP Request\/Response abstraction\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-http_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-http_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHTTP Request\/Response abstraction\u003C\/p\u003E","words":4,"readTime":null,"lang":"en"}}},"projects\/avris-polonisator":{"key":"projects\/avris-polonisator","type":"article","published":true,"meta":{"createdAt":"2018-01-10T19:14:14+01:00","publishedAt":"2018-01-10T19:12:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Polonisator","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-polonisator"},"content":{"en":{"slug":"avris-polonisator","title":"Avris Polonisator","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-polonisator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHp0lEQVRIiX2XyY8kRxXGf2+JyKyurupletp4DB6DwWAbY2GxGFmAQTIGIUCAWAySBQc4gDjwJ3DnxgGBOMMJcWGRQOwSSGxiszEWNh5vY2s801t1VXdlRjwOWTNGgAhlZKaUsXzxffHifSk33nR7RKkIQdQKUTF3aikEgYrgapgqyZ3l8pRaK0RABAKICMJQRAQRAYKrJSJWtV57EhURUBHMHROhaUZ4hBARlFqQAAFKKQjDwKo6ABWFWkmq9KsJEFm141p7EQBBVV6cXK6+C1ELokbEi\/0MIamhteBXOwhKUIkADUF0mIwQVB0Q+lIxBEUIUUx1xcawEGT4trpWN8PdWC47RCBiWKCIoqu+poqbkVTxEIVaVgQPjBCBhKBquCkmgonipkhUaq3UWoYB3IfV14qqXZNKRYhaCYKNzU32r+wBFUIQh6gFVYEAMyWZkfwqIAFUoK7YEhDRlQyGopgZ2RJrTQPRM18saNxpkpM9UWullJ6+FBCG\/VIrANdft8vp0QyoA2kRqOYVKMV0kDib4qKJiA4JA6notU0qqNlArSVUFBVDxRk3Y7ZGG+zNDtBQogSNJ9QzRCFE6PtuYEjg\/I038twTTyISSICpIASQEImVZEoyxTVl+mAVMXY1VkB1YEcNUyO7ky2hGCKJJidefnad4\/mM067jupfsslzMmR0eYSJkV2pU7nnX23ns4UeY5oYghsgCVAdRVEEEkinZDQ9NSFrJhVADTBRVQ0Vxc1yN7BkXIZmTJJG0YXt7gw996iNsb23ys2\/\/gKcuPIU16yQfommysc4973w7D\/38V2y2I6AQEQMYFVTATDAdWHMXnNwgvVNrrPQFUEQNNUfEcHNUE262qol73\/NWHvj8x3j0d3\/ju1\/5FonCLdefI2rl6HiGZ+OTX\/oiv\/vO93npdMqydNToiSiDdLqKrjTsoZwUU3Bpx9SuILUO51AAYog4aolkjqqRzGlTZs2dT3\/uw9z\/wXuZ7R3x\/a99l6wjttZabn7lOY4PXuBgfsI7v\/AJkgr1wtO85vpdZos5J\/2SUntK7UAryQ0zwV1JLqRkuKxNkWUPpRIw7BEUkYSKIZ7I6rQpsZYSDzx4H\/d\/8F4A\/vzLv5JomKxPWF9rOLqy4PwbXse73ncP3jb8+svfYHdnA42Og8Og7xMlBkAhFdUgZcddSEnxLLiMJpB7KCChEIqgIA6aMHWSOTkl7rzz5bz\/o++4lhIOn59x5rqz3HB+l\/O3v4yX3fUKxjtTIoKnfvgLxqNMqeu0TU9uKkilRkffL4naoQaqgbmRG8eT4Ew2oC9EyAAmhugyHNeE4sjqAHzws++5djIDvPsz9\/GfJSJ45he\/Z3npBc7edIbTg0x3vM9UO8QqYkGtHbU\/RehRE8yVlDPeNLhOJqTCkGdQPJSEkcXJYWQ1Mspdd97IDTds\/xeAfy+1FB770W85evQx2rHSbqxx9taX0h+MObwoqCwROpBMlIRIHSIsOZYz1ozwyeaEUoAVQ4bg4bRitCgtRlOFu9\/8yv8LZnbpgIe\/9yuWly8xagCFbjFnfrnDZcnaRkPtynD2GKgkZCWXumO5RZsR\/pLtEX0f1AI1FA1FMVIICaMNpSnCLa\/Y+Z9AFodz\/v7Lv\/LMHx4hS8eorUPqqBAd1FODRskjJZJiEiuZEmqKpYzmBkkN5BH+2t2G+UnH8rSw7CulVEqtSAgSFSuCibCztXYNxPFswYVHn+GJPz3OMw\/9kyY61rwQqeBUslZCAyxgOeRKSUHywE0wEzQlJLeQDHKG3IC3+Pu2nuX4pDKbdRweV2Z9cHQK8yWcdLDshdLD17\/6TRbHC\/ZfOOT4yiG5FBKFRKXVysh6ximYtpXlWoVJkEJobbAZUjrUA8uG1aDrDGNCd2pomzjYW6OjRe69fSembeLkZLBKbpkQp+KEJApO1UxfYTRex3PD0dExO2fOMDs8WuU4Y3tjnW5+zDjD5kjZbgvXbxV2d4zxWHjy4j6zxYKSOzbP3cDPf\/wbnrh4yrSt7O5OOO2CXz98jKxvboemjKhhKeFNi6jhucFTxlKDqpGblre95U2c2dxib2+P7a0zXLmyz9ZkyvK058x0wv4Le9x0bodxysTJjM1xor\/8LOu6IGlPsp7Ncc8td66xf3HGpYuHTEbg0nP27vuY\/+Un+K0f+DjN+pS+Qjue4KlB1RFzkidEDGHIO7a1wSOX9rnjtpspXWFz4xytG8dXDpnnhp2bz7IUYTE\/YdLusFDjuD9FxkabKtUqJ02ls022Xw37s8dJI6Hxnn5vzvpt9+MFYzZfgCWWR0eIHAM6eKEYDPjgheDyc89Cqfz04lPUkxOohWyGlEAisFpIDN54LWUmyZm4s9Ek1pLgWljLMDvpeOMdU57eU+qVnukIJvvP8qp3vx7fu\/APll2HeqaWijcjePEfAgE8JVQViSBqoDEA0FqRvr9m8Gt3ioux\/\/yTtLnFRdhYn3JmuolHZT4\/ZGs64Y+POM9dGPH8wQlPXD5hlINGl7y3fxrZufnWqKXQL5fU7pQ0niAhlOUJmpohHdQezy3A4LkBrYEiSFz10IMX1wiEiongKriAUslmqAZ93yEUdifORmtcWQw2t3G4+zz8C1qOQnwD4bZcAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-polonisator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn extension to Avris Localisator and Avris Stringer introducing support for the Polish language.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-polonisator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHp0lEQVRIiX2XyY8kRxXGf2+JyKyurupletp4DB6DwWAbY2GxGFmAQTIGIUCAWAySBQc4gDjwJ3DnxgGBOMMJcWGRQOwSSGxiszEWNh5vY2s801t1VXdlRjwOWTNGgAhlZKaUsXzxffHifSk33nR7RKkIQdQKUTF3aikEgYrgapgqyZ3l8pRaK0RABAKICMJQRAQRAYKrJSJWtV57EhURUBHMHROhaUZ4hBARlFqQAAFKKQjDwKo6ABWFWkmq9KsJEFm141p7EQBBVV6cXK6+C1ELokbEi\/0MIamhteBXOwhKUIkADUF0mIwQVB0Q+lIxBEUIUUx1xcawEGT4trpWN8PdWC47RCBiWKCIoqu+poqbkVTxEIVaVgQPjBCBhKBquCkmgonipkhUaq3UWoYB3IfV14qqXZNKRYhaCYKNzU32r+wBFUIQh6gFVYEAMyWZkfwqIAFUoK7YEhDRlQyGopgZ2RJrTQPRM18saNxpkpM9UWullJ6+FBCG\/VIrANdft8vp0QyoA2kRqOYVKMV0kDib4qKJiA4JA6notU0qqNlArSVUFBVDxRk3Y7ZGG+zNDtBQogSNJ9QzRCFE6PtuYEjg\/I038twTTyISSICpIASQEImVZEoyxTVl+mAVMXY1VkB1YEcNUyO7ky2hGCKJJidefnad4\/mM067jupfsslzMmR0eYSJkV2pU7nnX23ns4UeY5oYghsgCVAdRVEEEkinZDQ9NSFrJhVADTBRVQ0Vxc1yN7BkXIZmTJJG0YXt7gw996iNsb23ys2\/\/gKcuPIU16yQfommysc4973w7D\/38V2y2I6AQEQMYFVTATDAdWHMXnNwgvVNrrPQFUEQNNUfEcHNUE262qol73\/NWHvj8x3j0d3\/ju1\/5FonCLdefI2rl6HiGZ+OTX\/oiv\/vO93npdMqydNToiSiDdLqKrjTsoZwUU3Bpx9SuILUO51AAYog4aolkjqqRzGlTZs2dT3\/uw9z\/wXuZ7R3x\/a99l6wjttZabn7lOY4PXuBgfsI7v\/AJkgr1wtO85vpdZos5J\/2SUntK7UAryQ0zwV1JLqRkuKxNkWUPpRIw7BEUkYSKIZ7I6rQpsZYSDzx4H\/d\/8F4A\/vzLv5JomKxPWF9rOLqy4PwbXse73ncP3jb8+svfYHdnA42Og8Og7xMlBkAhFdUgZcddSEnxLLiMJpB7KCChEIqgIA6aMHWSOTkl7rzz5bz\/o++4lhIOn59x5rqz3HB+l\/O3v4yX3fUKxjtTIoKnfvgLxqNMqeu0TU9uKkilRkffL4naoQaqgbmRG8eT4Ew2oC9EyAAmhugyHNeE4sjqAHzws++5djIDvPsz9\/GfJSJ45he\/Z3npBc7edIbTg0x3vM9UO8QqYkGtHbU\/RehRE8yVlDPeNLhOJqTCkGdQPJSEkcXJYWQ1Mspdd97IDTds\/xeAfy+1FB770W85evQx2rHSbqxx9taX0h+MObwoqCwROpBMlIRIHSIsOZYz1ozwyeaEUoAVQ4bg4bRitCgtRlOFu9\/8yv8LZnbpgIe\/9yuWly8xagCFbjFnfrnDZcnaRkPtynD2GKgkZCWXumO5RZsR\/pLtEX0f1AI1FA1FMVIICaMNpSnCLa\/Y+Z9AFodz\/v7Lv\/LMHx4hS8eorUPqqBAd1FODRskjJZJiEiuZEmqKpYzmBkkN5BH+2t2G+UnH8rSw7CulVEqtSAgSFSuCibCztXYNxPFswYVHn+GJPz3OMw\/9kyY61rwQqeBUslZCAyxgOeRKSUHywE0wEzQlJLeQDHKG3IC3+Pu2nuX4pDKbdRweV2Z9cHQK8yWcdLDshdLD17\/6TRbHC\/ZfOOT4yiG5FBKFRKXVysh6ximYtpXlWoVJkEJobbAZUjrUA8uG1aDrDGNCd2pomzjYW6OjRe69fSembeLkZLBKbpkQp+KEJApO1UxfYTRex3PD0dExO2fOMDs8WuU4Y3tjnW5+zDjD5kjZbgvXbxV2d4zxWHjy4j6zxYKSOzbP3cDPf\/wbnrh4yrSt7O5OOO2CXz98jKxvboemjKhhKeFNi6jhucFTxlKDqpGblre95U2c2dxib2+P7a0zXLmyz9ZkyvK058x0wv4Le9x0bodxysTJjM1xor\/8LOu6IGlPsp7Ncc8td66xf3HGpYuHTEbg0nP27vuY\/+Un+K0f+DjN+pS+Qjue4KlB1RFzkidEDGHIO7a1wSOX9rnjtpspXWFz4xytG8dXDpnnhp2bz7IUYTE\/YdLusFDjuD9FxkabKtUqJ02ls022Xw37s8dJI6Hxnn5vzvpt9+MFYzZfgCWWR0eIHAM6eKEYDPjgheDyc89Cqfz04lPUkxOohWyGlEAisFpIDN54LWUmyZm4s9Ek1pLgWljLMDvpeOMdU57eU+qVnukIJvvP8qp3vx7fu\/APll2HeqaWijcjePEfAgE8JVQViSBqoDEA0FqRvr9m8Gt3ioux\/\/yTtLnFRdhYn3JmuolHZT4\/ZGs64Y+POM9dGPH8wQlPXD5hlINGl7y3fxrZufnWqKXQL5fU7pQ0niAhlOUJmpohHdQezy3A4LkBrYEiSFz10IMX1wiEiongKriAUslmqAZ93yEUdifORmtcWQw2t3G4+zz8C1qOQnwD4bZcAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-polonisator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn extension to Avris Localisator and Avris Stringer introducing support for the Polish language.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["library","locale","localisation","localization","php","polish","translation"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-polonisator_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-polonisator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-polonisator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn extension to Avris Localisator and Avris Stringer introducing support for the Polish language.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-polonisator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-polonisator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn extension to Avris Localisator and Avris Stringer introducing support for the Polish language.\u003C\/p\u003E","words":14,"readTime":null,"lang":"en"}}},"projects\/avris-stringer":{"key":"projects\/avris-stringer","type":"article","published":true,"meta":{"createdAt":"2018-01-10T19:12:52+01:00","publishedAt":"2018-01-10T19:10:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Stringer","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-stringer"},"content":{"en":{"slug":"avris-stringer","title":"Avris Stringer","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-stringer_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2X268lRRXGf+tS1b33PnufM7fDneGuiDoRJZIQA5IgEIMGjRc0IfqgDxof\/BN8980Ho\/FZn4wviIlGI5BAAmi8wIBEYAYYBgLMnMs+t91dtXzoPYNRY6Wru5Ouy1ffV6vW13L1NbdElIoQRK0QFXOnlkIQqAiuhqmS3FksDqi1QgREIICIIAxFRBARILhQImJZ68UnUREBFcHcMRGaZoRHCBFBqQUJEKCUgjAMrKoDUFGolaRKv5wAkWU7LrYXARBU5f3J5cK7ELUgakS8388QkhpaC36hg6AElQjQEESHyQhB1QGhLxVDUIQQxVSXbAwLQYZvy2t5M9yNxaJDBCKGBYoouuxrqrgZSRUPUahlSfDACBFICKqGm2IimChuikSl1kqtZRjAfVh9rajaRalUhKiVIFhdW2Pj3HmgQgjiELWgKhBgpiQzkl8AJIAK1CVbAiK6lMFQFDMjW2LcNBA9u3t7NO40ycmeqLVSSk9fCgjDfqkVgMsuWedgew7UgbQIVPMSlGI6SJxNcdFERIeEgVT04iYV1Gyg1hIqioqh4kyaCYdGq5yfb6KhRAkaT6hniEKI0PfdwJDA8auv5q1TryESSICpIASQEImlZEoyxTVl+mAZMXYhVkB1YEcNUyO7ky2hGCKJJieuPbbCzu6cg67jkkvXWeztMt\/axkTIrtSo3PGZO3n55IvMckMQQ2QBqoMoqiACyZTshocmJC3lQqgBJoqqoaK4Oa5G9oyLkMxJkkjacPjwKl\/4xpc4fGiNP\/7yN7x++nWsWSH5EE3T1RXuuPtOnn\/sSdbaEVCIiAGMCipgJpgOrLkLTm6Q3qk1lvoCKKKGmiNiuDmqCTdb1sRd93+Kh777FV569gUe+dEvSBRuuuxyola2d+Z4Nr7+g+\/z7K8e5crZjEXpqNETUQbpdBldadhDOSmm4NJOqF1Bah3OoQDEEHHUEskcVSOZ06bM2J1vfueL3PvgXczPb\/PoTx4h64hD45brb7icnc132dzd5+7vfY2kQj39Bh+8bJ353i77\/YJSe0rtQCvJDTPBXUkupGS4jGfIoodSCRj2CIpIQsUQT2R12pQYp8RDD9\/DvQ\/eBcDfnniORMN0ZcrKuGH73B7HP\/FRPvPAHXjb8NQPf8b60VU0Oja3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklDhx4lo+9+VPX0wJW2\/POXLJMa44vs7xW67iqluvY3J0RkTw+m8fZzLKlLpC2\/TkpoJUanT0\/YKoHWqgGpgbuXE8Cc50FfpChAxgYoguw3FNKI4sD8CHv33\/xZMZ4L5v3cN\/lojgzON\/YvHOuxy75ggHm5luZ4OZdohVxIJaO2p\/gNCjJpgrKWe8aXCdTkmFIc+geCgJI4uTw8hqZJRbT1zNFVcc\/i8A\/15qKbz8u2fYfull2onSro45dvOV9JsTts4KKguEDiQTJSFShwhLjuWMNSN8ujalFGDJkCF4OK0YLUqL0VTh9k\/e8H\/BzN\/Z5OSvn2Tx3juMGkCh29tl970OlwXj1YbaleHsMVBJyFIudcdyizYj\/NLDI\/o+qAVqKBqKYqQQEkYbSlOEm647+j+B7G3t8o8nnuPMn18kS8eorUPqqBAd1AODRskjJZJiEkuZEmqKpYzmBkkN5BH+4fWG3f2OxUFh0VdKqZRakRAkKlYEE+HoofFFEDvzPU6\/dIZTf32FM8+\/ShMdYy9EKjiVrJXQAAtYDLlSUpA8cBPMBE0JyS0kg5whN+At\/sChN9nZr8znHVs7lXkfbB\/A7gL2O1j0Qunhpz\/+OXs7e2y8u8XOuS1yKSQKiUqrlZH1TFIwayuLcYVpkEJobbAZUjrUA8uG1aDrDGNKd2Bom9g8P6ajRe665WjM2sT+\/mCV3DIhTsUJSRScqpm+QoiCOuPxhDY37O\/tsTqdEn2PUWkUJhmmGY5NgssOFdaPGpOJ8NrZDeZ7e5TcsXb5FTz2+6c5dfaAWVtZX59y0AVPndxBVtYOh6aMqGEp4U2LqOG5wVPGUoOqkZsW80TyzO23fZyjq6vsbM\/Jnil9ZeyJ6bghRWHWZjZeO0Pu5hxZUQ5NIGlPsp61Sc9NJ8ZsnJ3zztktpiNw6Tl2+z3s\/v0P+M2f\/yrNyoy+QjuZ4qlB1RFzkidEDGHIOxKClEq\/0lJnK6ysBdtbO2gENA3X3XglJ0++yqKDbVZZG62xk5ScjDZVqlX2m0pnaxz+AGzMXyGNhMZ7+vO7rHzoXrxgzHf3wBKL7W1EdgAdvFAMBnzwQiClQqm8e7bywv4+1EI2Q0ogETz9zNNYFbQWxikzTc7UndUmMU6Ca2GcYb7fcdtHZrxxXqnnemYjmG68yY33fQw\/f\/qfLLoO9UwtFW9G8P4\/BAJ4SqgqEkHUQGMAoLUifX\/R4NfuABdj4+3XaHOLi7C6MuPIbA2Pyu7uFodmU\/7yovPW6RFvb+5z6r19RjlodMFn+zeQo9ffHLUU+sWC2h2QJlMkhLLYR1MzpIPa47kFGDw3oDVQBIkLHnrw4hqBUDERXAUXUCrZDNWg7zuEwvrUWW2Nc3uDzW0cbj8O\/wI5fjvJRZLhiwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-stringer_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA set of useful, string-related helpers:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-stringer_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2X268lRRXGf+tS1b33PnufM7fDneGuiDoRJZIQA5IgEIMGjRc0IfqgDxof\/BN8980Ho\/FZn4wviIlGI5BAAmi8wIBEYAYYBgLMnMs+t91dtXzoPYNRY6Wru5Ouy1ffV6vW13L1NbdElIoQRK0QFXOnlkIQqAiuhqmS3FksDqi1QgREIICIIAxFRBARILhQImJZ68UnUREBFcHcMRGaZoRHCBFBqQUJEKCUgjAMrKoDUFGolaRKv5wAkWU7LrYXARBU5f3J5cK7ELUgakS8388QkhpaC36hg6AElQjQEESHyQhB1QGhLxVDUIQQxVSXbAwLQYZvy2t5M9yNxaJDBCKGBYoouuxrqrgZSRUPUahlSfDACBFICKqGm2IimChuikSl1kqtZRjAfVh9rajaRalUhKiVIFhdW2Pj3HmgQgjiELWgKhBgpiQzkl8AJIAK1CVbAiK6lMFQFDMjW2LcNBA9u3t7NO40ycmeqLVSSk9fCgjDfqkVgMsuWedgew7UgbQIVPMSlGI6SJxNcdFERIeEgVT04iYV1Gyg1hIqioqh4kyaCYdGq5yfb6KhRAkaT6hniEKI0PfdwJDA8auv5q1TryESSICpIASQEImlZEoyxTVl+mAZMXYhVkB1YEcNUyO7ky2hGCKJJieuPbbCzu6cg67jkkvXWeztMt\/axkTIrtSo3PGZO3n55IvMckMQQ2QBqoMoqiACyZTshocmJC3lQqgBJoqqoaK4Oa5G9oyLkMxJkkjacPjwKl\/4xpc4fGiNP\/7yN7x++nWsWSH5EE3T1RXuuPtOnn\/sSdbaEVCIiAGMCipgJpgOrLkLTm6Q3qk1lvoCKKKGmiNiuDmqCTdb1sRd93+Kh777FV569gUe+dEvSBRuuuxyola2d+Z4Nr7+g+\/z7K8e5crZjEXpqNETUQbpdBldadhDOSmm4NJOqF1Bah3OoQDEEHHUEskcVSOZ06bM2J1vfueL3PvgXczPb\/PoTx4h64hD45brb7icnc132dzd5+7vfY2kQj39Bh+8bJ353i77\/YJSe0rtQCvJDTPBXUkupGS4jGfIoodSCRj2CIpIQsUQT2R12pQYp8RDD9\/DvQ\/eBcDfnniORMN0ZcrKuGH73B7HP\/FRPvPAHXjb8NQPf8b60VU0Oja3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklDhx4lo+9+VPX0wJW2\/POXLJMa44vs7xW67iqluvY3J0RkTw+m8fZzLKlLpC2\/TkpoJUanT0\/YKoHWqgGpgbuXE8Cc50FfpChAxgYoguw3FNKI4sD8CHv33\/xZMZ4L5v3cN\/lojgzON\/YvHOuxy75ggHm5luZ4OZdohVxIJaO2p\/gNCjJpgrKWe8aXCdTkmFIc+geCgJI4uTw8hqZJRbT1zNFVcc\/i8A\/15qKbz8u2fYfull2onSro45dvOV9JsTts4KKguEDiQTJSFShwhLjuWMNSN8ujalFGDJkCF4OK0YLUqL0VTh9k\/e8H\/BzN\/Z5OSvn2Tx3juMGkCh29tl970OlwXj1YbaleHsMVBJyFIudcdyizYj\/NLDI\/o+qAVqKBqKYqQQEkYbSlOEm647+j+B7G3t8o8nnuPMn18kS8eorUPqqBAd1AODRskjJZJiEkuZEmqKpYzmBkkN5BH+4fWG3f2OxUFh0VdKqZRakRAkKlYEE+HoofFFEDvzPU6\/dIZTf32FM8+\/ShMdYy9EKjiVrJXQAAtYDLlSUpA8cBPMBE0JyS0kg5whN+At\/sChN9nZr8znHVs7lXkfbB\/A7gL2O1j0Qunhpz\/+OXs7e2y8u8XOuS1yKSQKiUqrlZH1TFIwayuLcYVpkEJobbAZUjrUA8uG1aDrDGNKd2Bom9g8P6ajRe665WjM2sT+\/mCV3DIhTsUJSRScqpm+QoiCOuPxhDY37O\/tsTqdEn2PUWkUJhmmGY5NgssOFdaPGpOJ8NrZDeZ7e5TcsXb5FTz2+6c5dfaAWVtZX59y0AVPndxBVtYOh6aMqGEp4U2LqOG5wVPGUoOqkZsW80TyzO23fZyjq6vsbM\/Jnil9ZeyJ6bghRWHWZjZeO0Pu5hxZUQ5NIGlPsp61Sc9NJ8ZsnJ3zztktpiNw6Tl2+z3s\/v0P+M2f\/yrNyoy+QjuZ4qlB1RFzkidEDGHIOxKClEq\/0lJnK6ysBdtbO2gENA3X3XglJ0++yqKDbVZZG62xk5ScjDZVqlX2m0pnaxz+AGzMXyGNhMZ7+vO7rHzoXrxgzHf3wBKL7W1EdgAdvFAMBnzwQiClQqm8e7bywv4+1EI2Q0ogETz9zNNYFbQWxikzTc7UndUmMU6Ca2GcYb7fcdtHZrxxXqnnemYjmG68yY33fQw\/f\/qfLLoO9UwtFW9G8P4\/BAJ4SqgqEkHUQGMAoLUifX\/R4NfuABdj4+3XaHOLi7C6MuPIbA2Pyu7uFodmU\/7yovPW6RFvb+5z6r19RjlodMFn+zeQo9ffHLUU+sWC2h2QJlMkhLLYR1MzpIPa47kFGDw3oDVQBIkLHnrw4hqBUDERXAUXUCrZDNWg7zuEwvrUWW2Nc3uDzW0cbj8O\/wI5fjvJRZLhiwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-stringer_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA set of useful, string-related helpers:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EconvertCase\u003C\/li\u003E\n\u003Cli\u003EcleanUrl\u003C\/li\u003E\n\u003Cli\u003EnumberInWords\u003C\/li\u003E\n\u003Cli\u003EtimeInWords\u003C\/li\u003E\n\u003Cli\u003EtimeDiff\u003C\/li\u003E\n\u003Cli\u003Elistify\u003C\/li\u003E\n\u003Cli\u003Ephone\u003C\/li\u003E\n\u003Cli\u003EarabicToRoman\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["helper","language","library","numbers","php","string","time","words"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-stringer_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-stringer_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-stringer_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA set of useful, string-related helpers:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-stringer_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-stringer_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA set of useful, string-related helpers:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EconvertCase\u003C\/li\u003E\n\u003Cli\u003EcleanUrl\u003C\/li\u003E\n\u003Cli\u003EnumberInWords\u003C\/li\u003E\n\u003Cli\u003EtimeInWords\u003C\/li\u003E\n\u003Cli\u003EtimeDiff\u003C\/li\u003E\n\u003Cli\u003Elistify\u003C\/li\u003E\n\u003Cli\u003Ephone\u003C\/li\u003E\n\u003Cli\u003EarabicToRoman\u003C\/li\u003E\n\u003C\/ul\u003E","words":14,"readTime":null,"lang":"en"}}},"projects\/avris-localisator":{"key":"projects\/avris-localisator","type":"article","published":true,"meta":{"createdAt":"2018-01-10T19:09:58+01:00","publishedAt":"2018-01-10T19:08:00+01:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Localisator","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-localisator"},"content":{"en":{"slug":"avris-localisator","title":"Avris Localisator","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-localisator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHmUlEQVRIiX2Xya8dRxXGf2eo6r73vfsGx37GQ+wMEAgBLBCISBFKiJRJCBAgZgnBAhYgFvwJ7NmxQCDWsEJsGCQQiEFKJAiIIQkhIiGOY0xkx2+67973bnfVYdHXDgJEqSepq7q++r4653wt5267J6JUhCBqhaiYO7UUgkBFcDVMleTOYnFErRUiIAIBRARhaCKCiADBjRYRy7PevBMVEVARzB0ToWlGeIQQEZRakAABSikIw4dVdQAqCrWSVOmXEyCy7MfN\/iIAgqq8NrnceBaiFkSNiNfGGUJSQ2vBbwwQlKASARqC6DAZIag6IPSlYgiKEKKY6pKNYSHI8G55LC+Gu7FYdIhAxLBAEUWXY00VNyOp4iEKtSwJHhghAglB1XBTTAQTxU2RqNRaqbUMH3AfVl8rqnZTKhUhaiUI1jc22Lm+DVQIQRyiFlQFAsyUZEbyG4AEUIG6ZEtARJcyGIpiZmRLjJsGomc2n9O40yQne6LWSik9fSkgDPulVgBOndziaH8K1IG0CFTzEpRiOkicTXHRRESHhIFU9OYmFdRsoNYSKoqKoeKsNCtsjtbZnu6ioUQJGk+oZ4hCiND33cCQwPlz5\/jniy8hEkiAqSAEkBCJpWRKMsU1ZfpgGTF2I1ZAdWBHDVMju5MtoRgiiSYnbj+xysFsylHXcfJ1WyzmM6Z7+5gI2ZUalfsevp\/nn3mWtdwQxBBZgOogiiqIQDIlu+GhCUlLuRBqgImiaqgobo6rkT3jIiRzkiSSNhw7ts6HP\/tRjm1u8Ivv\/ZhLFy9hzSrJh2iarK9y34P38\/QvH2ejHQGFiBjAqKACZoLpwJq74OQG6Z1aY6kvgCJqqDkihpujmnCz5Zl44LH38MkvfZznnvwLP\/j6d0kU7jp1mqiV\/YMpno1Pf\/UrPPn9H3F2bY1F6ajRE1EG6XQZXWnYQzkppuDSrlC7gtQ65KEAxBBx1BLJHFUjmdOmzNidz33xIzzyoQeYbu\/zo2\/+gKwjNsctd77+NAe719idHfLglz9FUqFefJk3ndpiOp9x2C8otafUDrSS3DAT3JXkQkqGy3gNWfRQKgHDHkERSagY4omsTpsS45T45Gce4pEPPQDAn379FImGyeqE1XHD\/vU559\/5Nh5+\/3142\/DE177N1vF1NDp294K+T5QYAIVUVIOUHXchJcWz4DKaQO6hgIRCKIKCOGjC1Enm5JS4cOF2PvCx994sCXuvTLnl5AnOnN\/i\/D23cus77mDl+BoRwaWf\/IqVUabUVdqmJzcVpFKjo+8XRO1QA9XA3MiN40lwJuvQFyJkABNDdBmOa0JxZJkAP\/OFx25mZoBHP\/8Q\/9kigsu\/+h2Lq9c4cdstHO1muoMd1rRDrCIW1NpR+yOEHjXBXEk5402D62RCKgx1BsVDSRhZnBxGViOjvOPCOc6cOfZfAP691VJ4\/qe\/Zf+552lXlHZ9zIm7z9LvrrB3RVBZIHQgmSgJkTpEWHIsZ6wZ4ZONCaUAS4YMwcNpxWhRWoymCve++\/X\/F8z06i7P\/PBxFq9eZdQACt18xuzVDpcF4\/WG2pUh9xioJGQpl7pjuUWbEf66YyP6PqgFaigaimKkEBJGG0pThLvuOP4\/gcz3Zvz1109x+ffPkqVj1NahdFSIDuqRQaPkkRJJMYmlTAk1xVJGc4OkBvIIf8tWw+ywY3FUWPSVUiqlViQEiYoVwUQ4vjm+CeJgOufic5d58Y8vcPnpv9NEx9gLkQpOJWslNMACFkOtlBQkD9wEM0FTQnILySBnyA14i79\/8x8cHFam0469g8q0D\/aPYLaAww4WvVB6+NY3vsP8YM7OtT0Oru+RSyFRSFRarYysZyUFa21lMa4wCVIIrQ02Q0qHemDZsBp0nWFM6I4MbRO722M6WuSBe47HWps4PBysklsmxKk4IYmCUzXTV0CN1Izouh7XIWtnd86dPc3OtWskKquNMMlwfFw5tVnYOm6srAgvXdlhOp9TcsfG6TP88me\/4cUrR6y1la2tCUdd8MQzB8jqxrHQlBE1LCW8aRE1PDd4ylhqUDVy07Kysspdd9xOm5xx07K9O+eOs6c4trnJwd4B+9u7vOH8KepszkiD1grl6iU2VyBpT7KejZWeuy6M2bky5eqVPSYjcOk5ce9DzP78c\/zuD36CZnWNvkK7MsFTg6oj5iRPiBjCUHeyGm+89STz+SEuwnpXEIK5GfPGOXHnSa4fLWjaFjOhO5gR6Sw5GW2qVKscNpXONjj2RtiZvkAaCY339NszVt\/8CF4wprM5WGKxv4\/IAaCDF4rBgA9eCKRUrly6iNRKPTyEWshmSAkkAquFxOCNxykzSc7EnfUmMU6Ca2GcYXrY8a63rvHytlKv96yNYLLzD97w6Nvx7Yt\/Y9F1qGdqqXgzgtf+IRDAU0JVkQiiBhoDAK0V6fubBr92R7gYO6+8RJvbgcXVNW5Z28CjMpvtsbk24Q\/POv+8OOKV3UNefPWQUQ4aXfC+\/mXk+J13Ry2FfrGgdkeklQkSQlkcoqkZykHt8dwCDJ4b0BoogsQNDz14cY1AqJgIroILKJVshmrQ9x1CYWvirLfG9flgcxuHe8\/DvwDS\/jrrbBLcdQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-localisator_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA neat tool to localise messages.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-localisator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHmUlEQVRIiX2Xya8dRxXGf2eo6r73vfsGx37GQ+wMEAgBLBCISBFKiJRJCBAgZgnBAhYgFvwJ7NmxQCDWsEJsGCQQiEFKJAiIIQkhIiGOY0xkx2+67973bnfVYdHXDgJEqSepq7q++r4653wt5267J6JUhCBqhaiYO7UUgkBFcDVMleTOYnFErRUiIAIBRARhaCKCiADBjRYRy7PevBMVEVARzB0ToWlGeIQQEZRakAABSikIw4dVdQAqCrWSVOmXEyCy7MfN\/iIAgqq8NrnceBaiFkSNiNfGGUJSQ2vBbwwQlKASARqC6DAZIag6IPSlYgiKEKKY6pKNYSHI8G55LC+Gu7FYdIhAxLBAEUWXY00VNyOp4iEKtSwJHhghAglB1XBTTAQTxU2RqNRaqbUMH3AfVl8rqnZTKhUhaiUI1jc22Lm+DVQIQRyiFlQFAsyUZEbyG4AEUIG6ZEtARJcyGIpiZmRLjJsGomc2n9O40yQne6LWSik9fSkgDPulVgBOndziaH8K1IG0CFTzEpRiOkicTXHRRESHhIFU9OYmFdRsoNYSKoqKoeKsNCtsjtbZnu6ioUQJGk+oZ4hCiND33cCQwPlz5\/jniy8hEkiAqSAEkBCJpWRKMsU1ZfpgGTF2I1ZAdWBHDVMju5MtoRgiiSYnbj+xysFsylHXcfJ1WyzmM6Z7+5gI2ZUalfsevp\/nn3mWtdwQxBBZgOogiiqIQDIlu+GhCUlLuRBqgImiaqgobo6rkT3jIiRzkiSSNhw7ts6HP\/tRjm1u8Ivv\/ZhLFy9hzSrJh2iarK9y34P38\/QvH2ejHQGFiBjAqKACZoLpwJq74OQG6Z1aY6kvgCJqqDkihpujmnCz5Zl44LH38MkvfZznnvwLP\/j6d0kU7jp1mqiV\/YMpno1Pf\/UrPPn9H3F2bY1F6ajRE1EG6XQZXWnYQzkppuDSrlC7gtQ65KEAxBBx1BLJHFUjmdOmzNidz33xIzzyoQeYbu\/zo2\/+gKwjNsctd77+NAe719idHfLglz9FUqFefJk3ndpiOp9x2C8otafUDrSS3DAT3JXkQkqGy3gNWfRQKgHDHkERSagY4omsTpsS45T45Gce4pEPPQDAn379FImGyeqE1XHD\/vU559\/5Nh5+\/3142\/DE177N1vF1NDp294K+T5QYAIVUVIOUHXchJcWz4DKaQO6hgIRCKIKCOGjC1Enm5JS4cOF2PvCx994sCXuvTLnl5AnOnN\/i\/D23cus77mDl+BoRwaWf\/IqVUabUVdqmJzcVpFKjo+8XRO1QA9XA3MiN40lwJuvQFyJkABNDdBmOa0JxZJkAP\/OFx25mZoBHP\/8Q\/9kigsu\/+h2Lq9c4cdstHO1muoMd1rRDrCIW1NpR+yOEHjXBXEk5402D62RCKgx1BsVDSRhZnBxGViOjvOPCOc6cOfZfAP691VJ4\/qe\/Zf+552lXlHZ9zIm7z9LvrrB3RVBZIHQgmSgJkTpEWHIsZ6wZ4ZONCaUAS4YMwcNpxWhRWoymCve++\/X\/F8z06i7P\/PBxFq9eZdQACt18xuzVDpcF4\/WG2pUh9xioJGQpl7pjuUWbEf66YyP6PqgFaigaimKkEBJGG0pThLvuOP4\/gcz3Zvz1109x+ffPkqVj1NahdFSIDuqRQaPkkRJJMYmlTAk1xVJGc4OkBvIIf8tWw+ywY3FUWPSVUiqlViQEiYoVwUQ4vjm+CeJgOufic5d58Y8vcPnpv9NEx9gLkQpOJWslNMACFkOtlBQkD9wEM0FTQnILySBnyA14i79\/8x8cHFam0469g8q0D\/aPYLaAww4WvVB6+NY3vsP8YM7OtT0Oru+RSyFRSFRarYysZyUFa21lMa4wCVIIrQ02Q0qHemDZsBp0nWFM6I4MbRO722M6WuSBe47HWps4PBysklsmxKk4IYmCUzXTV0CN1Izouh7XIWtnd86dPc3OtWskKquNMMlwfFw5tVnYOm6srAgvXdlhOp9TcsfG6TP88me\/4cUrR6y1la2tCUdd8MQzB8jqxrHQlBE1LCW8aRE1PDd4ylhqUDVy07Kysspdd9xOm5xx07K9O+eOs6c4trnJwd4B+9u7vOH8KepszkiD1grl6iU2VyBpT7KejZWeuy6M2bky5eqVPSYjcOk5ce9DzP78c\/zuD36CZnWNvkK7MsFTg6oj5iRPiBjCUHeyGm+89STz+SEuwnpXEIK5GfPGOXHnSa4fLWjaFjOhO5gR6Sw5GW2qVKscNpXONjj2RtiZvkAaCY339NszVt\/8CF4wprM5WGKxv4\/IAaCDF4rBgA9eCKRUrly6iNRKPTyEWshmSAkkAquFxOCNxykzSc7EnfUmMU6Ca2GcYXrY8a63rvHytlKv96yNYLLzD97w6Nvx7Yt\/Y9F1qGdqqXgzgtf+IRDAU0JVkQiiBhoDAK0V6fubBr92R7gYO6+8RJvbgcXVNW5Z28CjMpvtsbk24Q\/POv+8OOKV3UNefPWQUQ4aXfC+\/mXk+J13Ry2FfrGgdkeklQkSQlkcoqkZykHt8dwCDJ4b0BoogsQNDz14cY1AqJgIroILKJVshmrQ9x1CYWvirLfG9flgcxuHe8\/DvwDS\/jrrbBLcdQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-localisator_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA neat tool to localise messages.\u003C\/p\u003E\n\u003Cp\u003ELocalisator uses three elements to translate your messages:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003ELocaleOrder \u2013 decides which language(s) should be used,\u003C\/li\u003E\n\u003Cli\u003EProviders \u2013 fetches a translation for a specific key from a source (file, database, cache, ...),\u003C\/li\u003E\n\u003Cli\u003ETransformers \u2013 modifies the translation with more advanced logic (pluralisation, fallback, nesting, ...).\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["i18n","language","library","locale","localisation","localization","php","translation"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-localisator_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-localisator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-localisator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA neat tool to localise messages.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-localisator_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-localisator_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA neat tool to localise messages.\u003C\/p\u003E\n\u003Cp\u003ELocalisator uses three elements to translate your messages:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003ELocaleOrder \u2013 decides which language(s) should be used,\u003C\/li\u003E\n\u003Cli\u003EProviders \u2013 fetches a translation for a specific key from a source (file, database, cache, ...),\u003C\/li\u003E\n\u003Cli\u003ETransformers \u2013 modifies the translation with more advanced logic (pluralisation, fallback, nesting, ...).\u003C\/li\u003E\n\u003C\/ul\u003E","words":47,"readTime":null,"lang":"en"}}},"projects\/avris-container":{"key":"projects\/avris-container","type":"article","published":true,"meta":{"createdAt":"2018-01-09T20:22:03+01:00","publishedAt":"2018-01-09T20:21:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Container","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-container"},"content":{"en":{"slug":"avris-container","title":"Avris Container","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2XyY8kRxXGf2+JyKyqruplZnq8zoA3MAYsNmFkIYwlLwgBAsRikBAc4ADiwJ\/AnRsHBOIMJ8TFgAQCgS3ZEptYjbEweLwNlsczvVR3V1dmxOOQNW0EiFBGZkoZyxffFy\/el3LuNXdElIoQRK0QFXOnlkIQqAiuhqmS3Fkuj6m1QgREIICIIAxFRBARILhaImJV68mTqIiAimDumAhNM8IjhIig1IIECFBKQRgGVtUBqCjUSlKlX02AyKodJ+1FAARVeXVyufouRC2IGhGv9jOEpIbWgl\/tIChBJQI0BNFhMkJQdUDoS8UQFCFEMdUVG8NCkOHb6lrdDHdjuewQgYhhgSKKrvqaKm5GUsVDFGpZETwwQgQSgqrhppgIJoqbIlGptVJrGQZwH1ZfK6p2IpWKELUSBOsbG+xcvgJUCEEcohZUBQLMlGRG8quABFCBumJLQERXMhiKYmZkS4ybBqLn8OiIxp0mOdkTtVZK6elLAWHYL7UCcO3ZbY7350AdSItANa9AKaaDxNkUF01EdEgYSEVPNqmgZgO1llBRVAwVZ9JM2Bytc2W+i4YSJWg8oZ4hCiFC33cDQwLnz53jn888i0ggAaaCEEBCJFaSKckU15Tpg1XE2NVYAdWBHTVMjexOtoRiiCSanHjtmTUODuccdx1nr9lmeXTIfG8fEyG7UqNy9\/3v4eknnmSWG4IYIgtQHURRBRFIpmQ3PDQhaSUXQg0wUVQNFcXNcTWyZ1yEZE6SRNKGra11PvLZj7G1ucHPv\/cjnrvwHNaskXyIpun6Gnff+x7+\/IvH2GhHQCEiBjAqqICZYDqw5i44uUF6p9ZY6QugiBpqjojh5qgm3GxVE\/e879089KVP8NSv\/8LDX\/8uicJt115H1Mr+wRzPxqe\/+hV+\/f0fcsNsxrJ01OiJKIN0uoquNOyhnBRTcGkn1K4gtQ7nUABiiDhqiWSOqpHMaVNm7M7nvvhRHvjwPcyv7PPDbz5M1hGb45abb7mOg91L7B4uuPfLnyKpUC88z+uv3WZ+dMiiX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjoM\/fxwIfvAeAPj\/6JRMN0bcrauGH\/8hHn3\/5m7v\/A3Xjb8PjXvs326XU0Onb3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklLjzztfywY+\/9yQl7L0059TZM1x\/fpvzd9zIjW+9icnpGRHBcz9+hMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTdegLETKAiSG6DMc1oTiyOgA\/84X3nZzMAA9+\/j7+s0QELzzyG5YvX+LMa05xvJvpDnaYaYdYRSyotaP2xwg9aoK5knLGmwbX6ZRUGPIMioeSMLI4OYysRkZ5653nuP76rf8C8O+llsLTP\/kV+089TTtR2vUxZ26\/gX53wt5FQWWJ0IFkoiRE6hBhybGcsWaETzemlAKsGDIED6cVo0VpMZoq3PXOW\/4vmPnLuzzxg8dYvvIyowZQ6I4OOXylw2XJeL2hdmU4ewxUErKSS92x3KLNCL9ma0TfB7VADUVDUYwUQsJoQ2mKcNtNp\/8nkKO9Q\/766J944bdPkqVj1NYhdVSIDuqxQaPkkRJJMYmVTAk1xVJGc4OkBvIIf+N2w+GiY3lcWPaVUiqlViQEiYoVwUQ4vTk+AXEwP+LCUy\/wzO\/\/zgt\/\/gdNdIy9EKngVLJWQgMsYDnkSklB8sBNMBM0JSS3kAxyhtyAt\/gHNl\/kYFGZzzv2DirzPtg\/hsMlLDpY9kLp4Vvf+A5HB0fsXNrj4PIeuRQShUSl1crIeiYpmLWV5bjCNEghtDbYDCkd6oFlw2rQdYYxpTs2tE3sXhnT0SL33HE6Zm1isRisklsmxKk4IYmCUzXTVwhR1BObm6fY29nFzWhSovGES2VrfQLHB0wznJkE124Wtk8bk4nw7MUd5kdHlNyxcd31\/OKnv+SZi8fM2sr29pTjLnj8iQNkbWMrNGVEDUsJb1pEDc8NnjKWGlSN3LSYJ971trdw8dIut95wltJVmmZE45mttTGH+wdMsjNrE9Ns7D1\/gTVZsDmBpD3JejYmPbfdOWbn4pyXL+4xHYFLz5m77uPwjz\/Db\/\/QJ2nWZvQV2skUTw2qjpiTPCFiCEPekRB8NuGmc7A1m7C7e0DfdUzHI3p3sAn7xx21KseLYFG3kFbJyWhTpVpl0VQ622DrdbAz\/ztpJDTe0185ZO0ND+AFY354BJZY7u8jcgDo4IViMOCDFwIplUsvVqRW6mIBtZDNkBJIBFYLicEbj1NmmpypO+tNYpwE18I4w3zR8Y43zXj+ilIv98xGMN15kVsffAt+5cLfWHYd6plaKt6M4NV\/CATwlFBVJIKogcYAQGtF+v7E4NfuGBdj56VnaXOLi7C+NuPUbAOPyuHhHpuzKb970vnnhREv7S545pUFoxw0uuT9\/fPI6Ztvj1oK\/XJJ7Y5JkykSQlku0NQM6aD2eG4BBs8NaA0UQeKqhx68uEYgVEwEV8EFlEo2QzXo+w6hsD111lvj8tFgcxuHu87DvwCrEznQnIJIIAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-container_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHlklEQVRIiX2XyY8kRxXGf2+JyKyqruplZnq8zoA3MAYsNmFkIYwlLwgBAsRikBAc4ADiwJ\/AnRsHBOIMJ8TFgAQCgS3ZEptYjbEweLwNlsczvVR3V1dmxOOQNW0EiFBGZkoZyxffFy\/el3LuNXdElIoQRK0QFXOnlkIQqAiuhqmS3Fkuj6m1QgREIICIIAxFRBARILhaImJV68mTqIiAimDumAhNM8IjhIig1IIECFBKQRgGVtUBqCjUSlKlX02AyKodJ+1FAARVeXVyufouRC2IGhGv9jOEpIbWgl\/tIChBJQI0BNFhMkJQdUDoS8UQFCFEMdUVG8NCkOHb6lrdDHdjuewQgYhhgSKKrvqaKm5GUsVDFGpZETwwQgQSgqrhppgIJoqbIlGptVJrGQZwH1ZfK6p2IpWKELUSBOsbG+xcvgJUCEEcohZUBQLMlGRG8quABFCBumJLQERXMhiKYmZkS4ybBqLn8OiIxp0mOdkTtVZK6elLAWHYL7UCcO3ZbY7350AdSItANa9AKaaDxNkUF01EdEgYSEVPNqmgZgO1llBRVAwVZ9JM2Bytc2W+i4YSJWg8oZ4hCiFC33cDQwLnz53jn888i0ggAaaCEEBCJFaSKckU15Tpg1XE2NVYAdWBHTVMjexOtoRiiCSanHjtmTUODuccdx1nr9lmeXTIfG8fEyG7UqNy9\/3v4eknnmSWG4IYIgtQHURRBRFIpmQ3PDQhaSUXQg0wUVQNFcXNcTWyZ1yEZE6SRNKGra11PvLZj7G1ucHPv\/cjnrvwHNaskXyIpun6Gnff+x7+\/IvH2GhHQCEiBjAqqICZYDqw5i44uUF6p9ZY6QugiBpqjojh5qgm3GxVE\/e879089KVP8NSv\/8LDX\/8uicJt115H1Mr+wRzPxqe\/+hV+\/f0fcsNsxrJ01OiJKIN0uoquNOyhnBRTcGkn1K4gtQ7nUABiiDhqiWSOqpHMaVNm7M7nvvhRHvjwPcyv7PPDbz5M1hGb45abb7mOg91L7B4uuPfLnyKpUC88z+uv3WZ+dMiiX1JqT6kdaCW5YSa4K8mFlAyX8QxZ9lAqAcMeQRFJqBjiiaxOmxLjlHjoM\/fxwIfvAeAPj\/6JRMN0bcrauGH\/8hHn3\/5m7v\/A3Xjb8PjXvs326XU0Onb3gr5PlBgAhVRUg5QddyElxbPgMppC7qGAhEIogoI4aMLUSebklLjzztfywY+\/9yQl7L0059TZM1x\/fpvzd9zIjW+9icnpGRHBcz9+hMkoU+oabdOTmwpSqdHR90uidqiBamBu5MbxJDjTdegLETKAiSG6DMc1oTiyOgA\/84X3nZzMAA9+\/j7+s0QELzzyG5YvX+LMa05xvJvpDnaYaYdYRSyotaP2xwg9aoK5knLGmwbX6ZRUGPIMioeSMLI4OYysRkZ5653nuP76rf8C8O+llsLTP\/kV+089TTtR2vUxZ26\/gX53wt5FQWWJ0IFkoiRE6hBhybGcsWaETzemlAKsGDIED6cVo0VpMZoq3PXOW\/4vmPnLuzzxg8dYvvIyowZQ6I4OOXylw2XJeL2hdmU4ewxUErKSS92x3KLNCL9ma0TfB7VADUVDUYwUQsJoQ2mKcNtNp\/8nkKO9Q\/766J944bdPkqVj1NYhdVSIDuqxQaPkkRJJMYmVTAk1xVJGc4OkBvIIf+N2w+GiY3lcWPaVUiqlViQEiYoVwUQ4vTk+AXEwP+LCUy\/wzO\/\/zgt\/\/gdNdIy9EKngVLJWQgMsYDnkSklB8sBNMBM0JSS3kAxyhtyAt\/gHNl\/kYFGZzzv2DirzPtg\/hsMlLDpY9kLp4Vvf+A5HB0fsXNrj4PIeuRQShUSl1crIeiYpmLWV5bjCNEghtDbYDCkd6oFlw2rQdYYxpTs2tE3sXhnT0SL33HE6Zm1isRisklsmxKk4IYmCUzXTVwhR1BObm6fY29nFzWhSovGES2VrfQLHB0wznJkE124Wtk8bk4nw7MUd5kdHlNyxcd31\/OKnv+SZi8fM2sr29pTjLnj8iQNkbWMrNGVEDUsJb1pEDc8NnjKWGlSN3LSYJ971trdw8dIut95wltJVmmZE45mttTGH+wdMsjNrE9Ns7D1\/gTVZsDmBpD3JejYmPbfdOWbn4pyXL+4xHYFLz5m77uPwjz\/Db\/\/QJ2nWZvQV2skUTw2qjpiTPCFiCEPekRB8NuGmc7A1m7C7e0DfdUzHI3p3sAn7xx21KseLYFG3kFbJyWhTpVpl0VQ622DrdbAz\/ztpJDTe0185ZO0ND+AFY354BJZY7u8jcgDo4IViMOCDFwIplUsvVqRW6mIBtZDNkBJIBFYLicEbj1NmmpypO+tNYpwE18I4w3zR8Y43zXj+ilIv98xGMN15kVsffAt+5cLfWHYd6plaKt6M4NV\/CATwlFBVJIKogcYAQGtF+v7E4NfuGBdj56VnaXOLi7C+NuPUbAOPyuHhHpuzKb970vnnhREv7S545pUFoxw0uuT9\/fPI6Ztvj1oK\/XJJ7Y5JkykSQlku0NQM6aD2eG4BBs8NaA0UQeKqhx68uEYgVEwEV8EFlEo2QzXo+w6hsD111lvj8tFgcxuHu87DvwCrEznQnIJIIAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\n\u003Ch3\u003EInstallation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs bash border\u0022\u003Ecomposer require avris\/container\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EUsage\u003C\/h3\u003E\n\u003Ch4\u003EBasics\u003C\/h4\u003E\n\u003Cp\u003EContainer resolves dependencies between defined services,\nin order to simplify the development process, avoid duplication of code,\nfacilitate interoperability and improve maintainability and testability.\nSee: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022\u003EDependency Injection pattern\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$parameterProvider = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E SimpleParameterProvider([\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027ROOT_DIR\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003E__DIR__\u003C\/span\u003E]);\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ parameter provider is optional\u003C\/span\u003E\n\n$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container($parameterProvider);\n\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027number\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E4\u003C\/span\u003E);\n$container-\u0026gt;set(Foo::class, \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Foo);\n$container-\u0026gt;setDefinition(Bar::class, [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027arguments\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$foo\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@\u0027\u003C\/span\u003E . Foo::class,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$dir\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027%ROOT_DIR%\/bar\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$number\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@number\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$float\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E69.123\u003C\/span\u003E,\n    ],\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027public\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E,\n]);\n$container-\u0026gt;setDefinition(BarInterface::class, Bar::class); \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ alias\u003C\/span\u003E\n\n$container-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027number\u0027\u003C\/span\u003E);              \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ 4\u003C\/span\u003E\n$container-\u0026gt;get(Foo::class);            \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ new Foo\u003C\/span\u003E\n$container-\u0026gt;get(BarInterface::class);   \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ new Bar(new Foo, __DIR__ . \u0027\/bar\u0027, 4, 69.123)\u003C\/span\u003E\n$container-\u0026gt;getParameter(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027ROOT_DIR\u0027\u003C\/span\u003E);   \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ __DIR__\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003EOptions\u003C\/h4\u003E\n\u003Cul\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eclass\u003C\/code\u003E \u2013 the class of the service, will default to the service name if not given.\nIf the given class implements the \u003Ccode\u003EResolver\u003C\/code\u003E interface, it will be instantiated,\nand it\u2019s \u003Ccode\u003Eresolve\u003C\/code\u003E method executed to provide an actual value to be put in the container.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Earguments\u003C\/code\u003E \u2013 constructor arguments.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Ecalls\u003C\/code\u003E \u2013 method calls to be executed right after constructing the service (setter injection etc.)\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0027calls\u0027 =\u0026gt; [\n    [\u0027setLogger\u0027, [\u0027@logger\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerA\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerB\u0027]],\n],\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Etags\u003C\/code\u003E \u2013 an array of string that help group similar services together; tagged services can be injected with \u003Ccode\u003E#tagName\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(HandlerA::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerB::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerC::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(Manager::class, [\u0027arguments\u0027 =\u0026gt; [\u0027$handlers\u0027 =\u0026gt; \u0027#handler\u0027]]);\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Efactory\u003C\/code\u003E -- determines if each \u003Ccode\u003Eget\u003C\/code\u003E should create a new service (\u003Ccode\u003Etrue\u003C\/code\u003E),\nor should one service be reused (\u003Ccode\u003Efalse\u003C\/code\u003E, default).\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eresolve\u003C\/code\u003E \u2013 instead of using \u003Ccode\u003Eclass\u003C\/code\u003E + \u003Ccode\u003Earguments\u003C\/code\u003E to construct the service,\nyou can use \u003Ccode\u003Eresolve\u003C\/code\u003E to define how it should be created:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(\u0027foo\u0027, [\u0027resolve\u0027 =\u0026gt; 4]); \/\/ 4\n$container-\u0026gt;setDefinition(\u0027language\u0027, [\u0027resolve\u0027 =\u0026gt; \u0027@Request.locale.language\u0027]); \/\/ $container-\u0026gt;get(\u0027Request\u0027)-\u0026gt;getLocale()-\u0026gt;getLanguage()\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Epublic\u003C\/code\u003E \u2013 determines if the service should be accessible directly with \u003Ccode\u003Eget\u003C\/code\u003E,\nor can it only be injected into other services.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch4\u003EContainerCompiler: autowiring and autoconfiguration\u003C\/h4\u003E\n\u003Cp\u003EUsually it\u2019s obvious, which service should be injected into another.\nFor instance when your service has a constructor argument \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface $cache\u003C\/code\u003E,\nand the container does have a service named \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E,\nthen explicitly writing \u003Ccode\u003E[\u0027arguments\u0027 =\u0026gt; [\u0027$cache\u0027 =\u0026gt; \u0027@Psr\\Cache\\CacheItemPoolInterface\u0027]\u003C\/code\u003E is redundant.\nYou can always specify the dependencies manually, then autowiring won\u0027t overwrite them.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is not magic \u2013 it just follows simple rules to determine,\nwhich service should be injected into the constructor:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eif the argument is a class which is defined in the container, use this service,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is a class which is not defined in the container,\ntry to autowire that class and create a private service out of it,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is an array and its name ends with \u003Ccode\u003Es\u003C\/code\u003E (e.g. \u003Ccode\u003Earray $helpers\u003C\/code\u003E),\ninject an array of services with a specific tag (\u003Ccode\u003E#helper\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003Eif the argument is of type \u003Ccode\u003EBag\u003C\/code\u003E, inject the config value with its name\n(e.g. \u003Ccode\u003EBag $localisation\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E@config.localisation\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Eif its name starts with \u003Ccode\u003Eenv\u003C\/code\u003E, inject a parameter:\n(e.g. \u003Ccode\u003Estring $envCacheDir\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E%CACHE_DIR%\u003C\/code\u003E)\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, but there is a default value, just use it,\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, throw an exception \u2013 this argument should be defined explicitly.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAutoconfiguration is another way to make your life simpler.\nFor instance, if you\u2019re using \u003Ca href=\u0022https:\/\/twig.symfony.com\/\u0022\u003ETwig\u003C\/a\u003E,\nyou might want all the classes in your code that extend \u003Ccode\u003ETwig\\Extension\\AbstractExtension\u003C\/code\u003E\nto be automatically registered as twig extension.\nAutoconfiguration lets you define what default config (tags, public etc.) should be added to them.\u003C\/p\u003E\n\u003Cp\u003ETo use autowiring and autoconfiguration, run the \u003Ccode\u003EContainerCompiler\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container;\n\n$services = [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\\u0027 =\u0026gt; [\n        \u0027\u003C\/span\u003Edir\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027 =\u0026gt; \u0027\u003C\/span\u003E%MODULE_DIR%\/src\/\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027,\n        \u0027\u003C\/span\u003Eexclude\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027 =\u0026gt; [\u0027\u003C\/span\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E#^Entity\/#\u0027],\u003C\/span\u003E\n    ],\n\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\Foo\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027arguments\u0027\u003C\/span\u003E =\u0026gt; [\n            \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027$bar\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E5\u003C\/span\u003E,\n        ],\n    ],\n\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027App\\Bar\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027public\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E,\n    ],\n];\n\n$autoconfiguration = [\n    \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Twig\\Extension\\AbstractExtension\u0027\u003C\/span\u003E =\u0026gt; [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tags\u0027\u003C\/span\u003E =\u0026gt; [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027twigExtension\u0027\u003C\/span\u003E],\n    ],\n];\n\n$definitions = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E ContainerCompiler(\n    $container,\n    $services,\n    $autoconfiguration\n))-\u0026gt;compile();\n\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/** \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E ServiceDefinition $definition *\/\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eforeach\u003C\/span\u003E ($definitions \u003Cspan class=\u0022hljs-keyword\u0022\u003Eas\u003C\/span\u003E $name =\u0026gt; $definition) {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!$container-\u0026gt;has($name)) {\n        $container-\u0026gt;setDefinition($name, $definition);\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIn this example, the whole \u003Ccode\u003E%MODULE_DIR%\/src\/\u003C\/code\u003E except for (the \u003Ccode\u003E\/src\/Entity\u003C\/code\u003E dir) will be scanned for PHP files\nand all the found classes will be autowired as private services. If some of them are not used and not public,\nthey will be removed from the container.\u003C\/p\u003E\n\u003Cp\u003ECompiling the container has \u003Cstrong\u003Eno impact on performance\u003C\/strong\u003E on production environment,\nas long as you \u003Cstrong\u003Ecache the result of \u003Ccode\u003Ecompile()\u003C\/code\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch4\u003EServiceLocator\u003C\/h4\u003E\n\u003Cp\u003EService locator restricts access to services in the container only to a selected list of names:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$container = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Container();\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027abc\u0027\u003C\/span\u003E);\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027def\u0027\u003C\/span\u003E);\n$container-\u0026gt;set(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027secret\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027XYZ\u0027\u003C\/span\u003E);\n\n$locator = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E ServiceLocator($container, [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E]);\n\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027foo\u0027\u003C\/span\u003E);     \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ \u0027abc\u0027\u003C\/span\u003E\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027bar\u0027\u003C\/span\u003E);     \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ \u0027def\u0027\u003C\/span\u003E\n$locator-\u0026gt;get(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027secret\u0027\u003C\/span\u003E);  \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ Exception\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EContainerAssistedBuilder\u003C\/h3\u003E\n\u003Cp\u003E\u003Ccode\u003EContainerAssistedBuilder\u003C\/code\u003E can be used to join together a couple of \u003Ccode\u003EContainerBuilderExtension\u003C\/code\u003Es\nwhich encapsulate a set of service definitions that form a library together.\nFor an example, see \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Localisator\u0022\u003EAvris Localisator\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch4\u003EMicrus\u003C\/h4\u003E\n\u003Cp\u003EThis container was originally built as a part of the \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022\u003EMicrus framework\u003C\/a\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["autoconfiguration","autowiring","container","dependencies","dependency injection","library","php","programming"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-container_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-container_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-container_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA dependency injection container with autowiring\u003C\/p\u003E\n\u003Ch3\u003EInstallation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-bash\u0022\u003Ecomposer require avris\/container\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EUsage\u003C\/h3\u003E\n\u003Ch4\u003EBasics\u003C\/h4\u003E\n\u003Cp\u003EContainer resolves dependencies between defined services,\nin order to simplify the development process, avoid duplication of code,\nfacilitate interoperability and improve maintainability and testability.\nSee: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022\u003EDependency Injection pattern\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$parameterProvider = new SimpleParameterProvider([\u0027ROOT_DIR\u0027 =\u0026gt; __DIR__]);\n\/\/ parameter provider is optional\n\n$container = new Container($parameterProvider);\n\n$container-\u0026gt;set(\u0027number\u0027, 4);\n$container-\u0026gt;set(Foo::class, new Foo);\n$container-\u0026gt;setDefinition(Bar::class, [\n    \u0027arguments\u0027 =\u0026gt; [\n        \u0027$foo\u0027 =\u0026gt; \u0027@\u0027 . Foo::class,\n        \u0027$dir\u0027 =\u0026gt; \u0027%ROOT_DIR%\/bar\u0027,\n        \u0027$number\u0027 =\u0026gt; \u0027@number\u0027,\n        \u0027$float\u0027 =\u0026gt; 69.123,\n    ],\n    \u0027public\u0027 =\u0026gt; true,\n]);\n$container-\u0026gt;setDefinition(BarInterface::class, Bar::class); \/\/ alias\n\n$container-\u0026gt;get(\u0027number\u0027);              \/\/ 4\n$container-\u0026gt;get(Foo::class);            \/\/ new Foo\n$container-\u0026gt;get(BarInterface::class);   \/\/ new Bar(new Foo, __DIR__ . \u0027\/bar\u0027, 4, 69.123)\n$container-\u0026gt;getParameter(\u0027ROOT_DIR\u0027);   \/\/ __DIR__\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003EOptions\u003C\/h4\u003E\n\u003Cul\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eclass\u003C\/code\u003E \u2013 the class of the service, will default to the service name if not given.\nIf the given class implements the \u003Ccode\u003EResolver\u003C\/code\u003E interface, it will be instantiated,\nand it\u2019s \u003Ccode\u003Eresolve\u003C\/code\u003E method executed to provide an actual value to be put in the container.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Earguments\u003C\/code\u003E \u2013 constructor arguments.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Ecalls\u003C\/code\u003E \u2013 method calls to be executed right after constructing the service (setter injection etc.)\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0027calls\u0027 =\u0026gt; [\n    [\u0027setLogger\u0027, [\u0027@logger\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerA\u0027]],\n    [\u0027registerListener\u0027, [\u0027@listenerB\u0027]],\n],\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Etags\u003C\/code\u003E \u2013 an array of string that help group similar services together; tagged services can be injected with \u003Ccode\u003E#tagName\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(HandlerA::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerB::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(HandlerC::class, [\u0027tags\u0027 =\u0026gt; \u0027handler\u0027]);\n$container-\u0026gt;setDefinition(Manager::class, [\u0027arguments\u0027 =\u0026gt; [\u0027$handlers\u0027 =\u0026gt; \u0027#handler\u0027]]);\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Efactory\u003C\/code\u003E -- determines if each \u003Ccode\u003Eget\u003C\/code\u003E should create a new service (\u003Ccode\u003Etrue\u003C\/code\u003E),\nor should one service be reused (\u003Ccode\u003Efalse\u003C\/code\u003E, default).\u003C\/p\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Eresolve\u003C\/code\u003E \u2013 instead of using \u003Ccode\u003Eclass\u003C\/code\u003E + \u003Ccode\u003Earguments\u003C\/code\u003E to construct the service,\nyou can use \u003Ccode\u003Eresolve\u003C\/code\u003E to define how it should be created:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$container-\u0026gt;setDefinition(\u0027foo\u0027, [\u0027resolve\u0027 =\u0026gt; 4]); \/\/ 4\n$container-\u0026gt;setDefinition(\u0027language\u0027, [\u0027resolve\u0027 =\u0026gt; \u0027@Request.locale.language\u0027]); \/\/ $container-\u0026gt;get(\u0027Request\u0027)-\u0026gt;getLocale()-\u0026gt;getLanguage()\u003C\/code\u003E\u003C\/pre\u003E\n\u003C\/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ccode\u003Epublic\u003C\/code\u003E \u2013 determines if the service should be accessible directly with \u003Ccode\u003Eget\u003C\/code\u003E,\nor can it only be injected into other services.\u003C\/p\u003E\n\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch4\u003EContainerCompiler: autowiring and autoconfiguration\u003C\/h4\u003E\n\u003Cp\u003EUsually it\u2019s obvious, which service should be injected into another.\nFor instance when your service has a constructor argument \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface $cache\u003C\/code\u003E,\nand the container does have a service named \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E,\nthen explicitly writing \u003Ccode\u003E[\u0027arguments\u0027 =\u0026gt; [\u0027$cache\u0027 =\u0026gt; \u0027@Psr\\Cache\\CacheItemPoolInterface\u0027]\u003C\/code\u003E is redundant.\nYou can always specify the dependencies manually, then autowiring won\u0027t overwrite them.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is not magic \u2013 it just follows simple rules to determine,\nwhich service should be injected into the constructor:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eif the argument is a class which is defined in the container, use this service,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is a class which is not defined in the container,\ntry to autowire that class and create a private service out of it,\u003C\/li\u003E\n\u003Cli\u003Eif the argument is an array and its name ends with \u003Ccode\u003Es\u003C\/code\u003E (e.g. \u003Ccode\u003Earray $helpers\u003C\/code\u003E),\ninject an array of services with a specific tag (\u003Ccode\u003E#helper\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003Eif the argument is of type \u003Ccode\u003EBag\u003C\/code\u003E, inject the config value with its name\n(e.g. \u003Ccode\u003EBag $localisation\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E@config.localisation\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Eif its name starts with \u003Ccode\u003Eenv\u003C\/code\u003E, inject a parameter:\n(e.g. \u003Ccode\u003Estring $envCacheDir\u003C\/code\u003E -\u0026gt; \u003Ccode\u003E%CACHE_DIR%\u003C\/code\u003E)\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, but there is a default value, just use it,\u003C\/li\u003E\n\u003Cli\u003Eif none of the above is true, throw an exception \u2013 this argument should be defined explicitly.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAutoconfiguration is another way to make your life simpler.\nFor instance, if you\u2019re using \u003Ca href=\u0022https:\/\/twig.symfony.com\/\u0022\u003ETwig\u003C\/a\u003E,\nyou might want all the classes in your code that extend \u003Ccode\u003ETwig\\Extension\\AbstractExtension\u003C\/code\u003E\nto be automatically registered as twig extension.\nAutoconfiguration lets you define what default config (tags, public etc.) should be added to them.\u003C\/p\u003E\n\u003Cp\u003ETo use autowiring and autoconfiguration, run the \u003Ccode\u003EContainerCompiler\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$container = new Container;\n\n$services = [\n    \u0027App\\\u0027 =\u0026gt; [\n        \u0027dir\u0027 =\u0026gt; \u0027%MODULE_DIR%\/src\/\u0027,\n        \u0027exclude\u0027 =\u0026gt; [\u0027#^Entity\/#\u0027],\n    ],\n\n    \u0027App\\Foo\u0027 =\u0026gt; [\n        \u0027arguments\u0027 =\u0026gt; [\n            \u0027$bar\u0027 =\u0026gt; 5,\n        ],\n    ],\n\n    \u0027App\\Bar\u0027 =\u0026gt; [\n        \u0027public\u0027 =\u0026gt; true,\n    ],\n];\n\n$autoconfiguration = [\n    \u0027Twig\\Extension\\AbstractExtension\u0027 =\u0026gt; [\n        \u0027tags\u0027 =\u0026gt; [\u0027twigExtension\u0027],\n    ],\n];\n\n$definitions = new ContainerCompiler(\n    $container,\n    $services,\n    $autoconfiguration\n))-\u0026gt;compile();\n\n\/** @var ServiceDefinition $definition *\/\nforeach ($definitions as $name =\u0026gt; $definition) {\n    if (!$container-\u0026gt;has($name)) {\n        $container-\u0026gt;setDefinition($name, $definition);\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIn this example, the whole \u003Ccode\u003E%MODULE_DIR%\/src\/\u003C\/code\u003E except for (the \u003Ccode\u003E\/src\/Entity\u003C\/code\u003E dir) will be scanned for PHP files\nand all the found classes will be autowired as private services. If some of them are not used and not public,\nthey will be removed from the container.\u003C\/p\u003E\n\u003Cp\u003ECompiling the container has \u003Cstrong\u003Eno impact on performance\u003C\/strong\u003E on production environment,\nas long as you \u003Cstrong\u003Ecache the result of \u003Ccode\u003Ecompile()\u003C\/code\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch4\u003EServiceLocator\u003C\/h4\u003E\n\u003Cp\u003EService locator restricts access to services in the container only to a selected list of names:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$container = new Container();\n$container-\u0026gt;set(\u0027foo\u0027, \u0027abc\u0027);\n$container-\u0026gt;set(\u0027bar\u0027, \u0027def\u0027);\n$container-\u0026gt;set(\u0027secret\u0027, \u0027XYZ\u0027);\n\n$locator = new ServiceLocator($container, [\u0027foo\u0027, \u0027bar\u0027]);\n\n$locator-\u0026gt;get(\u0027foo\u0027);     \/\/ \u0027abc\u0027\n$locator-\u0026gt;get(\u0027bar\u0027);     \/\/ \u0027def\u0027\n$locator-\u0026gt;get(\u0027secret\u0027);  \/\/ Exception\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EContainerAssistedBuilder\u003C\/h3\u003E\n\u003Cp\u003E\u003Ccode\u003EContainerAssistedBuilder\u003C\/code\u003E can be used to join together a couple of \u003Ccode\u003EContainerBuilderExtension\u003C\/code\u003Es\nwhich encapsulate a set of service definitions that form a library together.\nFor an example, see \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Localisator\u0022\u003EAvris Localisator\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch4\u003EMicrus\u003C\/h4\u003E\n\u003Cp\u003EThis container was originally built as a part of the \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022\u003EMicrus framework\u003C\/a\u003E.\u003C\/p\u003E","words":868,"readTime":4,"lang":"en"}}},"projects\/avris-dispatcher":{"key":"projects\/avris-dispatcher","type":"article","published":true,"meta":{"createdAt":"2017-12-31T13:16:19+01:00","publishedAt":"2017-12-31T13:14:00+01:00","group":null,"links":[{"icon":"brands gitlab","colour":"primary","url":"https:\/\/gitlab.com\/Avris\/Dispatcher","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-dispatcher"},"content":{"en":{"slug":"avris-dispatcher","title":"Avris Dispatcher","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_small.png\u0022 alt=\u0022Avris Dispatcher\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHp0lEQVRIiX2X2a8lV3XGf2vYu+qce88dum\/f7nbb3QYbgzFgBSXCkoXsWPKAiEEkYpYQPJCHIB74E3jnjQcE4jl5ivJCiAICMUhYYogygONYmLjdbjdWT3c490xVey8e6nQbJVG2aleVVHv49vfttddXcvH+RyJKRQiiVoiKuVNLIQhUBFfDVEnurFZLaq0QAREIICIIQxERRAQI7pSIWNd690lUREBFMHdMhKYZ4RFCRFBqQQIEKKUgDAOr6gBUFGolqdKvJ0Bk3Y677UUABFV5a3K58y5ELYgaEW\/1M4SkhtaC3+kgKEElAjQE0WEyQlB1QOhLxRAUIUQx1TUbw0KQ4dv6Wt8Md2O16hCBiGGBIoqu+5oqbkZSxUMUalkTPDBCBBKCquGmmAgmipsiUam1UmsZBnAfVl8rqnZXKhUhaiUItnd2OLh1G6gQgjhELagKBJgpyYzkdwAJoAJ1zZaAiK5lMBTFzMiWGDcNRM9sPqdxp0lO9kStlVJ6+lJAGPZLrQCcP7vP8ngK1IG0CFTzGpRiOkicTXHRRESHhIFU9O4mFdRsoNYSKoqKoeJsNBvsjra5PT1EQ4kSNJ5QzxCFEKHvu4EhgUsXL\/L7V19DJJAAU0EIICESa8mUZIpryvTBOmLsTqyA6sCOGqZGdidbQjFEEk1OvO3MJiezKcuu4+y5fVbzGdOjY0yE7EqNyuPPPMErL77EVm4IYogsQHUQRRVEIJmS3fDQhKS1XAg1wERRNVQUN8fVyJ5xEZI5SRJJG06d2uYvP\/9xTu3u8KO\/\/yeuXL6CNZskH6Jpsr3J4089wW9+\/DN22hFQiIgBjAoqYCaYDqy5C05ukN6pNdb6AiiihpojYrg5qgk3W9fEkx\/6IJ\/+0id5+Zf\/yXe+\/nckCg+dv4eoleOTKZ6Nz371K\/zyH77LvVtbrEpHjZ6IMkin6+hKwx7KSTEFl3aD2hWk1uEcCkAMEUctkcxRNZI5bcqM3fnC3\/wVz37sSaa3j\/nuN79D1hG745YHHryHk8MbHM4WPPXlz5BUqJdf513n95nOZyz6FaX2lNqBVpIbZoK7klxIyXAZbyGrHkolYNgjKCIJFUM8kdVpU2KcEp\/+3NM8+7EnAfj3n\/6aRMNkc8LmuOH41pxLf\/o+nnn+cbxteOFr32Z\/bxuNjsOjoO8TJQZAIRXVIGXHXUhJ8Sy4jCaQeyggoRCKoCAOmjB1kjk5JR599G185BN\/fjclHL055fTZM1y4tM+lR+7jvve\/nY29LSKCK9\/7CRujTKmbtE1PbipIpUZH36+I2qEGqoG5kRvHk+BMtqEvRMgAJoboMhzXhOLI+gD83F9\/6O7JDPDcF5\/mf5aI4OpPfsXq+g3O3H+a5WGmOzlgSzvEKmJBrR21XyL0qAnmSsoZbxpcJxNSYcgzKB5Kwsji5DCyGhnl\/Y9e5MKFU\/8LwB+XWgqvfP8XHL\/8Cu2G0m6POfPwvfSHGxxdE1RWCB1IJkpCpA4RlhzLGWtG+GRnQinAmiFD8HBaMVqUFqOpwmMfePD\/BTO9fsiL\/\/gzVjevM2oAhW4+Y3azw2XFeLuhdmU4ewxUErKWS92x3KLNCD93akTfB7VADUVDUYwUQsJoQ2mK8NDb9\/5PIPOjGf\/1019z9V9eIkvHqK1D6qgQHdSlQaPkkRJJMYm1TAk1xVJGc4OkBvIIf89+w2zRsVoWVn2llEqpFQlBomJFMBH2dsd3QZxM51x++Sqv\/tvvuPqb\/6aJjrEXIhWcStZKaIAFrIZcKSlIHrgJZoKmhOQWkkHOkBvwFn9+9w1OFpXptOPopDLtg+MlzFaw6GDVC6WHb33jb5mfzDm4ccTJrSNyKSQKiUqrlZH1bKRgq62sxhUmQQqhtcFmSOlQDywbVoOuM4wJ3dLQNnF4e0xHizz5yF5stYnFYrBKbpkQp+KEJApO1UxfIUQ5e\/4Cy8WS2ckMU13nOGOUHY\/Cub0JLI45sxGc3y3s7xkbG8Jr1w6YzueU3LFzzwV+\/IOf8+q1JVttZX9\/wrILXnjxBNncORWaMqKGpYQ3LaKG5wZPGUsNqkZuWswTf\/HM07QW3Lh5SNdVVIxL5\/dJ3nJ04yZnT+8gyznn9rYox4f016+wuwFJe5L17Gz0PPTomINrU65fO2IyApeeM489zew\/fog\/\/NFP0Wxu0VdoNyZ4alB1xJzkCRFDGPKOhLB58R7m8yXteMW79k9x9doN8vYGB7dP8NPneHPRsTs+zdVbS8ZsEulecjLaVKlWWTSVznY49U44mP6ONBIa7+lvz9h897N4wZjO5mCJ1fExIieADl4oBgM+eCGQUvnnN64gtVIXC34eFVdFSiARWC0kBm88TplJcibubDeJcRJcC+MM00XHn713i9dvK\/VWz9YIJgdv8I7n\/gS\/ffm3rLoO9UwtFW9G8NY\/BAJ4SqgqEkHUQGMAoLUifX\/X4NduiYtx8OZrtLnFRdje3OL01g4eldnsiN2tCf\/6kvP7yyPePFzw6s0Foxw0uuLD\/evI3gMPRy2FfrWidkvSxgQJoawWaGqGdFB7PLcAg+cGtAaKIHHHQw9eXCMQKiaCq+ACSiWboRr0fYdQ2J84261xaz7Y3MbhsUvwB7\/yQ03P6NWiAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_small.png\u0022 alt=\u0022Avris Dispatcher\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn event dispatcher\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_big.png\u0022 alt=\u0022Avris Dispatcher\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHp0lEQVRIiX2X2a8lV3XGf2vYu+qce88dum\/f7nbb3QYbgzFgBSXCkoXsWPKAiEEkYpYQPJCHIB74E3jnjQcE4jl5ivJCiAICMUhYYogygONYmLjdbjdWT3c490xVey8e6nQbJVG2aleVVHv49vfttddXcvH+RyJKRQiiVoiKuVNLIQhUBFfDVEnurFZLaq0QAREIICIIQxERRAQI7pSIWNd690lUREBFMHdMhKYZ4RFCRFBqQQIEKKUgDAOr6gBUFGolqdKvJ0Bk3Y677UUABFV5a3K58y5ELYgaEW\/1M4SkhtaC3+kgKEElAjQE0WEyQlB1QOhLxRAUIUQx1TUbw0KQ4dv6Wt8Md2O16hCBiGGBIoqu+5oqbkZSxUMUalkTPDBCBBKCquGmmAgmipsiUam1UmsZBnAfVl8rqnZXKhUhaiUItnd2OLh1G6gQgjhELagKBJgpyYzkdwAJoAJ1zZaAiK5lMBTFzMiWGDcNRM9sPqdxp0lO9kStlVJ6+lJAGPZLrQCcP7vP8ngK1IG0CFTzGpRiOkicTXHRRESHhIFU9O4mFdRsoNYSKoqKoeJsNBvsjra5PT1EQ4kSNJ5QzxCFEKHvu4EhgUsXL\/L7V19DJJAAU0EIICESa8mUZIpryvTBOmLsTqyA6sCOGqZGdidbQjFEEk1OvO3MJiezKcuu4+y5fVbzGdOjY0yE7EqNyuPPPMErL77EVm4IYogsQHUQRRVEIJmS3fDQhKS1XAg1wERRNVQUN8fVyJ5xEZI5SRJJG06d2uYvP\/9xTu3u8KO\/\/yeuXL6CNZskH6Jpsr3J4089wW9+\/DN22hFQiIgBjAoqYCaYDqy5C05ukN6pNdb6AiiihpojYrg5qgk3W9fEkx\/6IJ\/+0id5+Zf\/yXe+\/nckCg+dv4eoleOTKZ6Nz371K\/zyH77LvVtbrEpHjZ6IMkin6+hKwx7KSTEFl3aD2hWk1uEcCkAMEUctkcxRNZI5bcqM3fnC3\/wVz37sSaa3j\/nuN79D1hG745YHHryHk8MbHM4WPPXlz5BUqJdf513n95nOZyz6FaX2lNqBVpIbZoK7klxIyXAZbyGrHkolYNgjKCIJFUM8kdVpU2KcEp\/+3NM8+7EnAfj3n\/6aRMNkc8LmuOH41pxLf\/o+nnn+cbxteOFr32Z\/bxuNjsOjoO8TJQZAIRXVIGXHXUhJ8Sy4jCaQeyggoRCKoCAOmjB1kjk5JR599G185BN\/fjclHL055fTZM1y4tM+lR+7jvve\/nY29LSKCK9\/7CRujTKmbtE1PbipIpUZH36+I2qEGqoG5kRvHk+BMtqEvRMgAJoboMhzXhOLI+gD83F9\/6O7JDPDcF5\/mf5aI4OpPfsXq+g3O3H+a5WGmOzlgSzvEKmJBrR21XyL0qAnmSsoZbxpcJxNSYcgzKB5Kwsji5DCyGhnl\/Y9e5MKFU\/8LwB+XWgqvfP8XHL\/8Cu2G0m6POfPwvfSHGxxdE1RWCB1IJkpCpA4RlhzLGWtG+GRnQinAmiFD8HBaMVqUFqOpwmMfePD\/BTO9fsiL\/\/gzVjevM2oAhW4+Y3azw2XFeLuhdmU4ewxUErKWS92x3KLNCD93akTfB7VADUVDUYwUQsJoQ2mK8NDb9\/5PIPOjGf\/1019z9V9eIkvHqK1D6qgQHdSlQaPkkRJJMYm1TAk1xVJGc4OkBvIIf89+w2zRsVoWVn2llEqpFQlBomJFMBH2dsd3QZxM51x++Sqv\/tvvuPqb\/6aJjrEXIhWcStZKaIAFrIZcKSlIHrgJZoKmhOQWkkHOkBvwFn9+9w1OFpXptOPopDLtg+MlzFaw6GDVC6WHb33jb5mfzDm4ccTJrSNyKSQKiUqrlZH1bKRgq62sxhUmQQqhtcFmSOlQDywbVoOuM4wJ3dLQNnF4e0xHizz5yF5stYnFYrBKbpkQp+KEJApO1UxfIUQ5e\/4Cy8WS2ckMU13nOGOUHY\/Cub0JLI45sxGc3y3s7xkbG8Jr1w6YzueU3LFzzwV+\/IOf8+q1JVttZX9\/wrILXnjxBNncORWaMqKGpYQ3LaKG5wZPGUsNqkZuWswTf\/HM07QW3Lh5SNdVVIxL5\/dJ3nJ04yZnT+8gyznn9rYox4f016+wuwFJe5L17Gz0PPTomINrU65fO2IyApeeM489zew\/fog\/\/NFP0Wxu0VdoNyZ4alB1xJzkCRFDGPKOhLB58R7m8yXteMW79k9x9doN8vYGB7dP8NPneHPRsTs+zdVbS8ZsEulecjLaVKlWWTSVznY49U44mP6ONBIa7+lvz9h897N4wZjO5mCJ1fExIieADl4oBgM+eCGQUvnnN64gtVIXC34eFVdFSiARWC0kBm88TplJcibubDeJcRJcC+MM00XHn713i9dvK\/VWz9YIJgdv8I7n\/gS\/ffm3rLoO9UwtFW9G8NY\/BAJ4SqgqEkHUQGMAoLUifX\/X4NduiYtx8OZrtLnFRdje3OL01g4eldnsiN2tCf\/6kvP7yyPePFzw6s0Foxw0uuLD\/evI3gMPRy2FfrWidkvSxgQJoawWaGqGdFB7PLcAg+cGtAaKIHHHQw9eXCMQKiaCq+ACSiWboRr0fYdQ2J84261xaz7Y3MbhsUvwB7\/yQ03P6NWiAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_big.png\u0022 alt=\u0022Avris Dispatcher\u0022 class=\u0022border\u0022 width=\u0022900\u0022 height=\u0022600\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn event dispatcher\u003C\/p\u003E\n\u003Ch3\u003EInstalation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs bash border\u0022\u003Ecomposer require avris\/dispatcher\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EEvent Definition\u003C\/h3\u003E\n\u003Cp\u003EAn event is an object that extends \u003Ccode\u003EAvris\\Dispatcher\\Event\u003C\/code\u003E.\nIt has to provide its name (used as an identifier for triggering it)\nand a setter and getter for its value (for instance if \u003Ccode\u003ERequestEvent\u003C\/code\u003E is supposed to produce a \u003Ccode\u003EResponse\u003C\/code\u003E, that response is the value).\u003C\/p\u003E\n\u003Cp\u003EFor example:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efinal\u003C\/span\u003E \u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ERequestEvent\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EEvent\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/** \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E RequestInterface *\/\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $request;\n\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/** \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E ResponseInterface *\/\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $response;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(RequestInterface $request)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;request = $request;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetName\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Estring\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027request\u0027\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetRequest\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003ERequestInterface\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;request;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetResponse\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: ?\u003Cspan class=\u0022hljs-title\u0022\u003EResponseInterface\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;response;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EsetResponse\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(ResponseInterface $response)\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Eself\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;response = $response;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EsetValue\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($value)\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003EEvent\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;response = $value;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetValue\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;response;\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EAttaching listeners\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$dispatcher = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E EventDispatcher();\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-params\u0022\u003E(RequestEvent $event)\u003C\/span\u003E \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (substr($event-\u0026gt;getRequest()-\u0026gt;getUrl(), \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E6\u003C\/span\u003E) === \u2018\/admin\u2019 \u0026amp;\u0026amp; !is_admin()) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Response(\u2019Forbidden\u2019, \u003Cspan class=\u0022hljs-number\u0022\u003E403\u003C\/span\u003E);\n    }\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EReturning anything other than \u003Ccode\u003Enull\u003C\/code\u003E will automatically set event\u2019s value\n(you can also do it explicitly with \u003Ccode\u003E$event-\u0026gt;setResponse($response)\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EAs a last argument of \u003Ccode\u003EattachListener\u003C\/code\u003E you can specify the priority of the listener, for example:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018one\u2019]);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018two\u2019]);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018three\u2019], \u003Cspan class=\u0022hljs-number\u0022\u003E-9\u003C\/span\u003E);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018four\u2019], \u003Cspan class=\u0022hljs-number\u0022\u003E9\u003C\/span\u003E);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe listeners will be triggered in order: \u003Ccode\u003Efour\u003C\/code\u003E, \u003Ccode\u003Eone\u003C\/code\u003E, \u003Ccode\u003Etwo\u003C\/code\u003E, \u003Ccode\u003Ethree\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003ETo stop propagation of an event, use \u003Ccode\u003E$event-\u0026gt;stopPropagation()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Ch3\u003ETriggering events\u003C\/h3\u003E\n\u003Cp\u003ETo trigger an event:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$response = $dispatcher-\u0026gt;trigger(new RequestEvent($request));\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAs you can see, the value of the event after executing the listeners will be returned for convenience\n(again, you can explicitly use \u003Ccode\u003E$event-\u0026gt;getResponse()\u003C\/code\u003E).\u003C\/p\u003E\n\u003Ch3\u003EEvent subscribers\u003C\/h3\u003E\n\u003Cp\u003EA subscriber is an object that defines event listeners in an elegant manner,\nencapsulating possibly multiple listeners related to one service.\u003C\/p\u003E\n\u003Cp\u003EIt needs to implement \u003Ccode\u003EAvris\\Dispatcher\\EventSubscriberInterface\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efinal\u003C\/span\u003E \u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EFooService\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eimplements\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EEventSubscriberInterface\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetSubscribedEvents\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Eiterable\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eyield\u003C\/span\u003E \u2018request\u2019 =\u0026gt; [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018onRequest\u2019];\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eyield\u003C\/span\u003E \u2018response:\u003Cspan class=\u0022hljs-number\u0022\u003E9\u003C\/span\u003E\u2019 =\u0026gt; [\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u2018onResponse\u2019]; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ priority 9\u003C\/span\u003E\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETo register them in the dispatcher:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$fooService = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E FooService();\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;dispatcher-\u0026gt;registerSubscriber($fooService);\n\u003C\/code\u003E\u003C\/pre\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["dispatcher","event","library","php"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-dispatcher_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-dispatcher_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_mini.png\u0022 alt=\u0022Avris Dispatcher\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn event dispatcher\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-dispatcher_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-dispatcher_mini.png\u0022 alt=\u0022Avris Dispatcher\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAn event dispatcher\u003C\/p\u003E\n\u003Ch3\u003EInstalation\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-bash\u0022\u003Ecomposer require avris\/dispatcher\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EEvent Definition\u003C\/h3\u003E\n\u003Cp\u003EAn event is an object that extends \u003Ccode\u003EAvris\\Dispatcher\\Event\u003C\/code\u003E.\nIt has to provide its name (used as an identifier for triggering it)\nand a setter and getter for its value (for instance if \u003Ccode\u003ERequestEvent\u003C\/code\u003E is supposed to produce a \u003Ccode\u003EResponse\u003C\/code\u003E, that response is the value).\u003C\/p\u003E\n\u003Cp\u003EFor example:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Efinal class RequestEvent extends Event\n{\n    \/** @var RequestInterface *\/\n    private $request;\n\n    \/** @var ResponseInterface *\/\n    private $response;\n\n    public function __construct(RequestInterface $request)\n    {\n        $this-\u0026gt;request = $request;\n    }\n\n    public function getName(): string\n    {\n        return \u0027request\u0027;\n    }\n\n    public function getRequest(): RequestInterface\n    {\n        return $this-\u0026gt;request;\n    }\n\n    public function getResponse(): ?ResponseInterface\n    {\n        return $this-\u0026gt;response;\n    }\n\n    public function setResponse(ResponseInterface $response): self\n    {\n        $this-\u0026gt;response = $response;\n\n        return $this;\n    }\n\n    public function setValue($value): Event\n    {\n        $this-\u0026gt;response = $value;\n\n        return $this;\n    }\n\n    public function getValue()\n    {\n        return $this-\u0026gt;response;\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EAttaching listeners\u003C\/h3\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$dispatcher = new EventDispatcher();\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, function (RequestEvent $event) {\n    if (substr($event-\u0026gt;getRequest()-\u0026gt;getUrl(), 0, 6) === \u2018\/admin\u2019 \u0026amp;\u0026amp; !is_admin()) {\n        return new Response(\u2019Forbidden\u2019, 403);\n    }\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EReturning anything other than \u003Ccode\u003Enull\u003C\/code\u003E will automatically set event\u2019s value\n(you can also do it explicitly with \u003Ccode\u003E$event-\u0026gt;setResponse($response)\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EAs a last argument of \u003Ccode\u003EattachListener\u003C\/code\u003E you can specify the priority of the listener, for example:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [$this, \u2018one\u2019]);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [$this, \u2018two\u2019]);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [$this, \u2018three\u2019], -9);\n$dispatcher-\u0026gt;attachListener(\u2019request\u2019, [$this, \u2018four\u2019], 9);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe listeners will be triggered in order: \u003Ccode\u003Efour\u003C\/code\u003E, \u003Ccode\u003Eone\u003C\/code\u003E, \u003Ccode\u003Etwo\u003C\/code\u003E, \u003Ccode\u003Ethree\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003ETo stop propagation of an event, use \u003Ccode\u003E$event-\u0026gt;stopPropagation()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Ch3\u003ETriggering events\u003C\/h3\u003E\n\u003Cp\u003ETo trigger an event:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$response = $dispatcher-\u0026gt;trigger(new RequestEvent($request));\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAs you can see, the value of the event after executing the listeners will be returned for convenience\n(again, you can explicitly use \u003Ccode\u003E$event-\u0026gt;getResponse()\u003C\/code\u003E).\u003C\/p\u003E\n\u003Ch3\u003EEvent subscribers\u003C\/h3\u003E\n\u003Cp\u003EA subscriber is an object that defines event listeners in an elegant manner,\nencapsulating possibly multiple listeners related to one service.\u003C\/p\u003E\n\u003Cp\u003EIt needs to implement \u003Ccode\u003EAvris\\Dispatcher\\EventSubscriberInterface\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Efinal class FooService implements EventSubscriberInterface\n{\n    public function getSubscribedEvents(): iterable\n    {\n        yield \u2018request\u2019 =\u0026gt; [$this, \u2018onRequest\u2019];\n        yield \u2018response:9\u2019 =\u0026gt; [$this, \u2018onResponse\u2019]; \/\/ priority 9\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETo register them in the dispatcher:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$fooService = new FooService();\n$this-\u0026gt;dispatcher-\u0026gt;registerSubscriber($fooService);\u003C\/code\u003E\u003C\/pre\u003E","words":349,"readTime":2,"lang":"en"}}}}}