{"id":413,"date":"2015-10-17T10:30:26","date_gmt":"2015-10-17T10:30:26","guid":{"rendered":"http:\/\/www.audero.it\/blog\/?p=413"},"modified":"2025-05-04T22:08:16","modified_gmt":"2025-05-04T22:08:16","slug":"upload-files-on-github-using-github-js","status":"publish","type":"post","link":"https:\/\/www.audero.it\/blog\/2015\/10\/17\/upload-files-on-github-using-github-js\/","title":{"rendered":"Upload files on GitHub using Github.js"},"content":{"rendered":"<p>For a few months now, I have been working on a project that employs the <a href=\"https:\/\/developer.github.com\/v3\/\" target=\"_blank\" rel=\"noopener\">GitHub APIs<\/a>. The application I&#8217;m\u00a0building is completely client-side and provides a feature to upload files to a repository on GitHub. To simplify the\u00a0interaction with the API, I&#8217;m\u00a0using a library called <a href=\"https:\/\/github.com\/github-tools\/github\" target=\"_blank\" rel=\"noopener\">Github.js<\/a>.<\/p>\n<p>Developing this feature has not been\u00a0straightforward since\u00a0the documentation of the library lacks examples of this type, or even mention if it&#8217;s possible at all. Moreover, I\u00a0wasn&#8217;t able to find any example on the web. Apparently, this functionality\u00a0is of interest for many people as demonstrated by <a href=\"https:\/\/stackoverflow.com\/questions\/6668283\/github-api-write-to-repo\" target=\"_blank\" rel=\"noopener\">this question on StackOverflow<\/a> and <a href=\"https:\/\/github.com\/github-tools\/github\/issues\/172\" target=\"_blank\" rel=\"noopener\">this issue opened on the Github.js&#8217; repository<\/a>. With a bit of study of the library&#8217;s source I was eventually\u00a0able to develop\u00a0the functionality, so I thought to write a post to share my experience and the solution I came up with.<br \/>\n<!--more--><br \/>\nIn this article, I&#8217;ll explain how to upload any file on a repository on GitHub using Github.js and discuss a couple of major issues you might face. If you want to see (a better version of) the code developed for this article in action, you can browse and download it from <a href=\"https:\/\/github.com\/AurelioDeRosa\/upload-files-github.js\">the repository I&#8217;ve created on GitHub<\/a>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"794\" data-permalink=\"https:\/\/www.audero.it\/blog\/2015\/10\/17\/upload-files-on-github-using-github-js\/github-social-coding\/\" data-orig-file=\"https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2015\/10\/github-social-coding.jpg\" data-orig-size=\"959,625\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2015\/10\/github-social-coding.jpg\" class=\"aligncenter size-full wp-image-794\" src=\"https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2015\/10\/github-social-coding.jpg\" alt=\"github social coding\" width=\"959\" height=\"625\" srcset=\"https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2015\/10\/github-social-coding.jpg 959w, https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2015\/10\/github-social-coding-300x196.jpg 300w\" sizes=\"auto, (max-width: 959px) 100vw, 959px\" \/><\/p>\n<h2>Saving text-based files with Github.js<\/h2>\n<p><a href=\"https:\/\/github.com\/github-tools\/github\" target=\"_blank\" rel=\"noopener\">Github.js<\/a> exposes different methods that make the\u00a0interaction with the GitHub API easier. To save a text-based file on GitHub, such as Markdown or HTML, the code needed is quite short and simple.<\/p>\n<p>To start, you have to download and include Github.js in your project. Once done, you create a new instance of the <code>Github<\/code> object exposed by the library and create an object representing the repository you want to work with. Finally, you create a new file on the repository (or update it if the file already exists) with the content you want using a method of the library called <code>write()<\/code>. In the Git parlance, creating or updating a file means <em>commit<\/em>. Therefore, you also need to specify a commit message.<\/p>\n<p>The code that implements these steps should look like the following snippet:<\/p>\n<pre><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ Creates a new instance of the Github object exposed by Github.js\nvar github = new Github({\n  username: 'YOUR_USERNAME',\n  password: 'YOUR_PASSWORD',\n  auth: 'basic'\n});\n\n\/\/ Creates an object representing the repository you want to work with\nvar repository = github.getRepo('A_USERNAME', 'A_REPOSITORY_NAME');\n\n\/\/ Creates a new file (or updates it if the file already exists)\n\/\/ with the content provided\nrepository.write(\n   'BRANCH_NAME', \/\/ e.g. 'master'\n   'path\/to\/file', \/\/ e.g. 'blog\/index.md'\n   'THE_CONTENT', \/\/ e.g. 'Hello world, this is my new content'\n   'YOUR_COMMIT_MESSAGE', \/\/ e.g. 'Created new index'\n   function(err) {}\n);\n<\/pre>\n<p>At the moment, it isn&#8217;t possible to create or update more than one file with one commit using the GitHub API, thus using Github.js. So, every time you call the <code>write()<\/code> method, a new commit will be created.<\/p>\n<p>The GitHub API accepts data that represent the content of the file in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Base64\">Base64<\/a>. In the previous example I was able to provide a simple string because when <code>write()<\/code> Github.js converts it into the appropriate format (Base64)\u00a0using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/btoa\" target=\"_blank\" rel=\"noopener\">window.btoa()<\/a> method.\u00a0As you&#8217;ll learn in the remainder of the article, this feature will turn into an issue when dealing with non text-based files, but this won&#8217;t be a problem with the solution I&#8217;ll explain.<\/p>\n<h2>Uploading files with Github.js<\/h2>\n<p>To let your web application upload files on GitHub with Github.js, you need a way to select these files. Luckily, HTML has a native element designed for this purpose:<\/p>\n<pre><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&amp;amp;lt;input type=&amp;amp;quot;file&amp;amp;quot; \/&amp;amp;gt;\n<\/pre>\n<p>In case you need to upload more than one file, you can use the <code>multiple<\/code> attribute as shown below:<\/p>\n<pre><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&amp;amp;lt;input type=&amp;amp;quot;file&amp;amp;quot; multiple \/&amp;amp;gt;\n<\/pre>\n<p>With this element in place, you&#8217;re able to select one or more files but nothing more than that happens. So, you have to write the code that reads the content of the selected files and upload them on GitHub. Let&#8217;s start with the first task.<\/p>\n<h3>Reading files with JavaScript<\/h3>\n<p>The first task can be achieved by employing <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/FileReader\" target=\"_blank\" rel=\"noopener\"><code>FileReader<\/code><\/a> and its <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/FileReader\/readAsDataURL\" target=\"_blank\" rel=\"noopener\"><code>readAsDataURL()<\/code> method<\/a>. <code>readAsDataURL()<\/code> accepts a <code>Blob<\/code> or a <code>File<\/code> object and gives you the content as a Base64 encoded string. In the previous sentence I&#8217;ve used the word <em>gives<\/em> instead of <em>return<\/em> on purpose. In fact, the method itself doesn&#8217;t return the content\u00a0(it returns <code>undefined<\/code>) because the read operation is asynchronous. To retrieve the content you have to listen for the <code>loadend<\/code> event which\u00a0is fired when the read operation is completed.<\/p>\n<p>To better understand how this mechanism works, let&#8217;s create a function called <code>readFile()<\/code> that accepts a <code>File<\/code> instance and reads its content. To avoid the issue known as <a href=\"https:\/\/web.archive.org\/web\/20231031154655\/https:\/\/strongloop.com\/strongblog\/node-js-callback-hell-promises-generators\/\" target=\"_blank\" rel=\"noopener\">callback hell<\/a>, the function will return a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Promise\" target=\"_blank\" rel=\"noopener\">Promise<\/a>. If you need a primer on Promises, I suggest you to read the article <a href=\"https:\/\/web.dev\/articles\/promises\" target=\"_blank\" rel=\"noopener\"><cite>JavaScript Promises, There and back again<\/cite><\/a> by <cite><a href=\"https:\/\/jakearchibald.com\/\" target=\"_blank\" rel=\"noopener\">Jake Archibald<\/a><\/cite>.<\/p>\n<p>The <code>readFile()<\/code> function resolves the Promise if the read is successful or reject it if an error occurs. When the Promise is resolved, the function provides an object with\u00a0two properties: <code>filename<\/code> and <code>content<\/code>. The former specifies the name of the file. The latter defines the binary representation of the file&#8217;s content, with the information about its mime type and its\u00a0encoding removed. You may wonder why the content is binary encoded if <code>readAsDataURL()<\/code> returns the string in Base64. The reason is that we have to convert it to a binary encoding, using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/atob\" target=\"_blank\" rel=\"noopener\"><code>window.atob()<\/code><\/a> method, to compensate the opposite conversion that Github.js does on our behalf when calling\u00a0<code>write()<\/code>. If you don&#8217;t do that, Github.js will send to the GitHub API a string that is double encoded in Base64 (i.e. Github.js encodes in Base64 a string that is already in Base64). As a result, if you try to open the file in your browser via the GitHub web interface or download it, you will receive an error because the file isn&#8217;t encoded correctly.<\/p>\n<p>The code that implements the above description is shown below:<\/p>\n<pre><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction readFile(file) {\n   return new Promise(function (resolve, reject) {\n      var fileReader = new FileReader();\n\n      fileReader.addEventListener('load', function (event) {\n         var content = event.target.result;\n\n         \/\/ Strip out the information about the mime type of the file and the encoding\n         \/\/ at the beginning of the file (e.g. data:image\/gif;base64,).\n         content = atob(content.replace(\/^(.+,)\/, ''));\n\n         resolve({\n            filename: file.name,\n            content: content\n         });\n      });\n\n      fileReader.addEventListener('error', function (error) {\n         reject(error);\n      });\n\n      fileReader.readAsDataURL(file);\n   });\n}\n<\/pre>\n<p>The <code>readFile()<\/code> function enables us to read one or more files, so we are now ready to upload them. But before discussing how to do that, we have to create a support function to overcome an issue of the GitHub API. Let&#8217;s learn more.<\/p>\n<h3>Promisifying Github.js<\/h3>\n<p>The application I&#8217;m working on requires to upload one or more files at a time, no matter how many commits are created. In my first attempts, I thought to speed up the process by executing all the calls to <code>write()<\/code>, one for each file, in parallel. However, the process was always failing with a weird error message. While doing a bit of research to understand what the cause could be, I stumbled upon <a href=\"https:\/\/stackoverflow.com\/questions\/19576601\/github-api-issue-with-file-upload\" target=\"_blank\" rel=\"noopener\">this question on StackOverflow<\/a>, and specifically <a href=\"https:\/\/stackoverflow.com\/questions\/19576601\/github-api-issue-with-file-upload#comment29081581_19576601\" target=\"_blank\" rel=\"noopener\">this comment<\/a>:<\/p>\n<blockquote><p>I&#8217;m guessing you&#8217;re hitting a corner case with the API due to these sequential writes that are happening one after another. Can you please try putting a sleep in your script so that you wait for a second or two between calls? That should resolve the issue. We&#8217;re working on fixing this on our end, but I can&#8217;t make any Promises about when this will be resolved. Let me know if that doesn&#8217;t help.<\/p><\/blockquote>\n<p>Now, having a sleep in between the calls was a no go for me. So, I decided to promisify the <code>write()<\/code> method so that I could execute all the calls in sequence without having to resort to any sleep approach. This decision turned out to be a winner.<\/p>\n<p>The function to promisify <code>write()<\/code> is reported below:<\/p>\n<pre><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction saveFile(data) {\n   return new Promise(function(resolve, reject) {\n      data.repository.write(\n         data.branchName,\n         data.filename,\n         data.content,\n         data.commitTitle,\n         function(err) {\n            if (err) {\n               reject(err);\n            } else {\n               resolve(data.repository);\n            }\n         }\n      );\n   });\n}\n<\/pre>\n<p>With this code in place, I can introduce you to the last function needed.<\/p>\n<h3>Uploading files<\/h3>\n<p>To complete the feature we&#8217;re discussing, all we need is a function that accepts an array (or array-like object) of files to read and a commit message. I&#8217;ll call such function <code>uploadFiles()<\/code>. It&#8217;ll return a Promise that is resolved when all the files have been uploaded correctly or rejected in case of error. The body of the function is short but terse, and might be a bit complicated to understand. So, before showing the code let&#8217;s discuss it in depth.<\/p>\n<p>The first operation to perform is to read all the files provided and store the resulting Promises into an array. The read operations are executed in parallel to improve the application&#8217;s performance. To complete this step we&#8217;ll use the <code>readFile()<\/code> function discussed earlier and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array\/map\" target=\"_blank\" rel=\"noopener\"><code>map()<\/code><\/a>. To move to the next step, we have to wait until the read of all the files is completed. To achieve this goal, we&#8217;ll employ <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Promise\/all\" target=\"_blank\" rel=\"noopener\"><code>Promise.all()<\/code><\/a> and pass to it the array of Promises we created.<\/p>\n<p>Once all the Promises are resolved, the function can start sending the data to GitHub using <code>saveFile()<\/code>. As I mentioned before, unfortunately the requests must be sent in sequence and we can&#8217;t upload all the files at once with a single commit. This means that a new request has to start when the previous one is resolved. For this reason, we have to create a chain of <code>then()<\/code> calls. In addition, for each call to <code>then()<\/code>, a new commit will be created. The are many ways we can achieve this goal, the simplest of which is to use a <code>for<\/code> loop or a similar construct. Personally, I preferred to use a functional approach that employs <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Array\/reduce\" target=\"_blank\" rel=\"noopener\"><code>reduce()<\/code><\/a>. The chain of Promises created is the returned value of the function.<\/p>\n<p>The code of the <code>uploadFiles()<\/code> function is listed below:<\/p>\n<pre><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction uploadFiles(files, commitTitle) {\n   \/\/ Creates an array of Promises resolved when the content\n   \/\/ of the file provided is read successfully.\n   var filesPromises = &#x5B;].map.call(files, readFile);\n\n   return Promise\n      .all(filesPromises)\n      .then(function(files) {\n         return files.reduce(\n            function(promise, file) {\n               return promise.then(function() {\n                  \/\/ Upload the file on GitHub\n                  return gitHub.saveFile({\n                     repository: gitHub.repository,\n                     branchName: config.branchName,\n                     filename: file.filename,\n                     content: file.content,\n                     commitTitle: commitTitle\n                  });\n               });\n            },\n            Promise.resolve()\n         );\n      });\n}\n<\/pre>\n<p>The caller of <code>uploadFiles()<\/code> can use the returned Promise to show a successful message to the user once the whole process is completed, or an error message if an issue occurs at any stage. An example is shown below:<\/p>\n<pre><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nvar files = document.getElementById('file').files;\nvar commitTitle = 'Files uploaded';\n\nuploadFiles(files, commitTitle)\n   .then(function() {\n      alert('Your file has been saved correctly.');\n   })\n   .catch(function(err) {\n      console.error(err);\n      alert('Something went wrong. Please, try again.');\n   });\n<\/pre>\n<p>Done! You&#8217;re now ready to upload as many files as you want on GitHub via its API using Github.js.<\/p>\n<h2>Conclusions<\/h2>\n<p>In this tutorial I&#8217;ve explained how to use Github.js to upload files on GitHub via its APIs. Finding the solution to this problem wasn&#8217;t straightforward and I had to dig into the library&#8217;s source to fully understand what was going on. Overall it has been a good experience that let me understand a couple of important issues to take into account. Specifically, I learned that behind the scene Github.js converts a string into its Base64 equivalent using the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/btoa\" target=\"_blank\" rel=\"noopener\">window.btoa()<\/a> method. I also learned that the GitHub API doesn&#8217;t allow you to create or save multiple files with one commit, and that it has an issue with sequential writes that happens quickly one after another.<\/p>\n<p>If you want to see (a better version of) the code developed for this article in action, you can browse and download it from <a href=\"https:\/\/github.com\/AurelioDeRosa\/upload-files-github.js\">the repository I&#8217;ve created on GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a few months now, I have been working on a project that employs the <a href=\"https:\/\/developer.github.com\/v3\/\" target=\"_blank\" rel=\"noopener\">GitHub APIs<\/a>. The application I&#8217;m\u00a0building is completely client-side and provides a feature to upload files to a repository on GitHub. To simplify the\u00a0interaction with the API, I&#8217;m\u00a0using a library called <a href=\"https:\/\/github.com\/github-tools\/github\" target=\"_blank\" rel=\"noopener\">Github.js<\/a>.<\/p>\n<p>In this article, I&#8217;ll explain how to upload any file on a repository on GitHub using Github.js and discuss a couple of major issues you might face. If you want to see (a better version of) the code developed for this article in action, you can browse and download it from <a href=\"https:\/\/github.com\/AurelioDeRosa\/upload-files-github.js\">the repository I&#8217;ve created on GitHub<\/a>.<\/p>\n","protected":false},"author":1,"featured_media":495,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[52,51,54,53,46,11],"class_list":["post-413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","tag-api","tag-github","tag-github-api","tag-github-js","tag-javascript","tag-web"],"jetpack_featured_media_url":"https:\/\/www.audero.it\/blog\/wp-content\/uploads\/2016\/06\/github-octocat-logo.png","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9Or4e-6F","jetpack-related-posts":[{"id":339,"url":"https:\/\/www.audero.it\/blog\/2014\/10\/18\/state-web-notifications-api\/","url_meta":{"origin":413,"position":0},"title":"The State of the Web Notifications API","author":"Aurelio De Rosa","date":"October 18, 2014","format":false,"excerpt":"Today I was reviewing my HTML5 API demos repository to keep its information updated and relevant. In the last two weeks Google has released\u00a0Chrome 38, Opera has released Opera 25, and Mozilla has released Firefox 33.\u00a0Every time a new version of a browser is available, it may\u00a0introduce support for new\u2026","rel":"","context":"In &quot;JavaScript&quot;","block_context":{"text":"JavaScript","link":"https:\/\/www.audero.it\/blog\/category\/javascript\/"},"img":{"alt_text":"push notifications","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/10\/push-notifications.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/10\/push-notifications.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/10\/push-notifications.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":672,"url":"https:\/\/www.audero.it\/blog\/2017\/01\/18\/from-javascript-developer-to-javascript-engineer-find-all-celebrities-in-a-set-of-people\/","url_meta":{"origin":413,"position":1},"title":"From JavaScript developer to JavaScript engineer: find all celebrities in a set of people","author":"Aurelio De Rosa","date":"January 18, 2017","format":false,"excerpt":"In the first article of my series From JavaScript developer to JavaScript engineer titled From JavaScript developer to JavaScript engineer: Re-implementing ECMAScript 2015's String.prototype.repeat() method I've discussed how computer science concepts can help in writing better and more elegant software. Specifically, I've demonstrated how to use appropriate algorithms and data\u2026","rel":"","context":"In &quot;From JavaScript developer to JavaScript engineer&quot;","block_context":{"text":"From JavaScript developer to JavaScript engineer","link":"https:\/\/www.audero.it\/blog\/category\/javascript\/from-javascript-developer-to-javascript-engineer\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/oscars-2014-selfie.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/oscars-2014-selfie.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/oscars-2014-selfie.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":637,"url":"https:\/\/www.audero.it\/blog\/2016\/12\/16\/from-javascript-developer-to-javascript-engineer-re-implementing-ecmascript-2015s-string-prototype-repeat-method\/","url_meta":{"origin":413,"position":2},"title":"From JavaScript developer to JavaScript engineer: re-implementing ECMAScript 2015&#8217;s String.prototype.repeat() method","author":"Aurelio De Rosa","date":"December 16, 2016","format":false,"excerpt":"As developers, our work is to solve problems which often implies writing code. Some of the problems we face look really simple in nature, but their simplicity leads us to write sub-optimal solutions without even realizing it. JavaScript developers come from very different backgrounds, and assuming that everyone has the\u2026","rel":"","context":"In &quot;From JavaScript developer to JavaScript engineer&quot;","block_context":{"text":"From JavaScript developer to JavaScript engineer","link":"https:\/\/www.audero.it\/blog\/category\/javascript\/from-javascript-developer-to-javascript-engineer\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/time-complexity-comparison.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/time-complexity-comparison.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/time-complexity-comparison.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":404,"url":"https:\/\/www.audero.it\/blog\/2015\/07\/14\/trick-of-the-day-css-scroll-snap-points\/","url_meta":{"origin":413,"position":3},"title":"Trick of the day: CSS Scroll Snap Points","author":"Aurelio De Rosa","date":"July 14, 2015","format":false,"excerpt":"When you create a gallery, you usually want to implement a feature where every time the user clicks (or press the ENTER key) on an arrow, you move straight to the next (or previous) image. This effect can also be used to create a website that has several sections, each\u2026","rel":"","context":"In &quot;Trick of the day&quot;","block_context":{"text":"Trick of the day","link":"https:\/\/www.audero.it\/blog\/category\/trick-of-the-day\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2015\/07\/css-scroll-snap-points.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2015\/07\/css-scroll-snap-points.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2015\/07\/css-scroll-snap-points.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2015\/07\/css-scroll-snap-points.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2015\/07\/css-scroll-snap-points.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":329,"url":"https:\/\/www.audero.it\/blog\/2014\/09\/19\/resources-beginner-front-end-developers\/","url_meta":{"origin":413,"position":4},"title":"Resources for Beginner Front-end Developers","author":"Aurelio De Rosa","date":"September 19, 2014","format":false,"excerpt":"Few weeks ago I received an email from a developer asking me for suggestions on how to delve into the front-end world. After having replied to this email, I thought that it'd have been nice to share the same suggestions on my blog. That's exactly what you'll find in this\u2026","rel":"","context":"In &quot;Discussions &amp; Opinions&quot;","block_context":{"text":"Discussions &amp; Opinions","link":"https:\/\/www.audero.it\/blog\/category\/discussions-opinions\/"},"img":{"alt_text":"html5 css3 javascript logos","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/09\/front-end-stack.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/09\/front-end-stack.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/09\/front-end-stack.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/09\/front-end-stack.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2014\/09\/front-end-stack.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":626,"url":"https:\/\/www.audero.it\/blog\/2016\/12\/05\/monkey-patching-javascript\/","url_meta":{"origin":413,"position":5},"title":"Monkey patching in JavaScript","author":"Aurelio De Rosa","date":"December 5, 2016","format":false,"excerpt":"When working on a project, we often use libraries that implement methods that aren't built-in in the programming language in use but we need. These libraries don't cover all the possible methods, so they might lack one or more crucial features we need. When this happens, we have two choices:\u2026","rel":"","context":"In &quot;JavaScript&quot;","block_context":{"text":"JavaScript","link":"https:\/\/www.audero.it\/blog\/category\/javascript\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.audero.it\/blog\/wp-content\/uploads\/2016\/12\/monkey-patching.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/posts\/413","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/comments?post=413"}],"version-history":[{"count":44,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/posts\/413\/revisions"}],"predecessor-version":[{"id":1056,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/posts\/413\/revisions\/1056"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/media\/495"}],"wp:attachment":[{"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/media?parent=413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/categories?post=413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.audero.it\/blog\/wp-json\/wp\/v2\/tags?post=413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}