8,037 Matching Annotations
  1. Jun 2022
    1. SkoHub supports a novel approach for finding content on the web. The general idea is to extend the scope of Knowledge Organization Systems (KOS) to also act as communication hubs for publishers and information seekers. In effect, SkoHub allows to follow specific subjects in order to be notified when new content about that subject is published.
    1. Implementation using readAsText()

      ```html <input type="file" id="file" /> <button id="get-time">Get Time</button>

      <script> document.getElementById('get-time').onclick = function () { let file = document.getElementById('file').files[0]; let fr = new FileReader(); fr.onload = function (e) { let startTime = getTime(e.target.result, false); let endTime = getTime(e.target.result, true); alert(`Log time range: ${startTime} ~ ${endTime}`); } fr.readAsText(file); } function getTime(text, reverse) { let timeReg = /\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}/; for (let i = reverse ? text.length - 1 : 0; reverse ? i > -1 : i < text.length; reverse ? i-- : i++) { if (text[i].charCodeAt() === 10) { let snippet = text.substr(i + 1, 19); if (timeReg.exec(snippet)) { return snippet; } } } } </script>

      ```

      Implementation using readAsArrayBuffer()

      ```html <input type="file" id="file" /> <button id="get-time">Get Time</button>

      <script> document.getElementById('get-time').onclick = function () { let file = document.getElementById('file').files[0]; let fr = new FileReader(); let CHUNK_SIZE = 10 * 1024; let startTime, endTime; let reverse = false; fr.onload = function () { let buffer = new Uint8Array(fr.result); let timeReg = /\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}/; for (let i = reverse ? buffer.length - 1 : 0; reverse ? i > -1 : i < buffer.length; reverse ? i-- : i++) { if (buffer[i] === 10) { let snippet = new TextDecoder('utf-8').decode(buffer.slice(i + 1, i + 20)); if (timeReg.exec(snippet)) { if (!reverse) { startTime = snippet; reverse = true; seek(); } else { endTime = snippet; alert(`Log time range: ${startTime} ~ ${endTime}`); } break; } } } } seek(); function seek() { let start = reverse ? file.size - CHUNK_SIZE : 0; let end = reverse ? file.size : CHUNK_SIZE; let slice = file.slice(start, end); fr.readAsArrayBuffer(slice); } } </script>

      ```

    1. ```html

      <input type="file" id="file-selector" multiple>

      <script> const fileSelector = document.getElementById('file-selector'); fileSelector.addEventListener('change', (event) => { const fileList = event.target.files; console.log(fileList); }); </script>

      ```

    1. The dataset read-only property of the HTMLElement interface provides read/write access to custom data attributes (data-*) on elements. It exposes a map of strings (DOMStringMap) with an entry for each data-* attribute.

      ```html

      <div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>John Doe</div>

      ```

      ```js const el = document.querySelector('#user');

      // el.id === 'user' // el.dataset.id === '1234567890' // el.dataset.user === 'johndoe' // el.dataset.dateOfBirth === ''

      // set a data attribute el.dataset.dateOfBirth = '1960-10-03'; // Result on JS: el.dataset.dateOfBirth === '1960-10-03' // Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth="1960-10-03">John Doe</div>

      delete el.dataset.dateOfBirth; // Result on JS: el.dataset.dateOfBirth === undefined // Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe">John Doe</div>

      if ('someDataAttr' in el.dataset === false) { el.dataset.someDataAttr = 'mydata'; // Result on JS: 'someDataAttr' in el.dataset === true // Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-some-data-attr="mydata">John Doe</div> } ```

    1. ```js if(window.location.href.endsWith('sitemap.xml')){

      const xmlStr = (
          `<?xml version="1.0" encoding="UTF-8"?>
              <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
                  <url><loc>https://erikmartinjordan.com</loc></url>
              </urlset>
          `
      );
      
      let blob = new Blob([xmlStr], {type: "text/xml"});
      let url = URL.createObjectURL(blob);
      window.open(url, "_self");
      URL.revokeObjectURL(url);
      

      } ```

    1. Using the download attribute to save a <canvas> as a PNGTo save a <canvas> element's contents as an image, you can create a link with a download attribute and the canvas data as a data: URL: Example painting app with save link

      ```html

      Paint by holding down the mouse button and moving it. Download my painting

      <canvas width="300" height="300"></canvas>

      ```

      css html { font-family: sans-serif; } canvas { background: #fff; border: 1px dashed; } a { display: inline-block; background: #69c; color: #fff; padding: 5px 10px; }

      ```js var canvas = document.querySelector('canvas'), c = canvas.getContext('2d'); c.fillStyle = 'hotpink';

      function draw(x, y) { if (isDrawing) { c.beginPath(); c.arc(x, y, 10, 0, Math.PI*2); c.closePath(); c.fill(); } }

      canvas.addEventListener('mousemove', event => draw(event.offsetX, event.offsetY) ); canvas.addEventListener('mousedown', () => isDrawing = true); canvas.addEventListener('mouseup', () => isDrawing = false);

      document.querySelector('a').addEventListener('click', event => event.target.href = canvas.toDataURL() ); ```

    1. Highlight part of an element This example uses the Range.setStart() and Range.setEnd() methods to add part of an address to a range. The selected range is then highlighted using Range.surroundContents(). The address contains nine nodes: five text nodes, and four <br> elements.

      ```html

      Wyatt Earp<br> 101 E. Main St.<br> Dodge City, KS<br> 67801<br> USA


      Nodes in the original address:

        ```

        ```js const address = document.getElementById('address'); const log = document.getElementById('log');

        // Log info address.childNodes.forEach(node => { const li = document.createElement('li'); li.textContent = ${node.nodeName}, ${node.nodeValue}; log.appendChild(li); });

        // Highlight the street and city const startOffset = 2; // Start at third node: 101 E. Main St. const endOffset = 5; // End at fifth node: Dodge City, KS const range = document.createRange(); range.setStart(address, startOffset); range.setEnd(address, endOffset);

        const mark = document.createElement('mark'); range.surroundContents(mark); ```

      1. ```html

        <html> <head> <br /> <script> function noMondays() { var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false); var textNode = tw.nextNode(); while (textNode) { if (textNode.wholeText.match('Monday') || textNode.parentNode.getAttribute('id') == 'Monday') { textNode.parentNode.removeChild(textNode); } textNode = tw.nextNode(); } } function refresh() { window.location.reload( false ); // Reload our page. } </script>

        </head> <body>

        Monday, Joe bought a turkey.

        Tuesday, Bill bought a pound of nails.

        <div>Chuck called in sick Monday.</div>

        CALL supplier today!

        Wednesday's delivery was delayed.

        <button onclick="refresh()">Reload</button> <button onclick="noMondays()">Lose Mondays</button> </body>

        </html> ```

      1. You can also use get a feed directly with a username: https://www.youtube.com/feeds/videos.xml?user=<username> The one I use most is the one for playlists (if creators remember to use them). https://www.youtube.com/feeds/videos.xml?playlist_id=<playlist id>

        bash $ curl -s "https://www.youtube.com/c/TED" | grep -Po '"channelId":".+?"' | cut -d \" -f 4 | while read -r YTID ; do echo -n "Youtube-ID: $YTID " ; curl -s "https://www.youtube.com/feeds/videos.xml?channel_id=$YTID" | grep -m 1 -P -o "(?<=<title>).+(?=</title>)" ; done Youtube-ID: UCsT0YIqwnpJCM-mx7-gSA4Q TEDx Talks Youtube-ID: UCsooa4yRKGN_zEE8iknghZA TED-Ed Youtube-ID: UCy9b8cNJQmxX8Y2bdE6mQNw TED Audio Collective Youtube-ID: UCBjBZmguQzn6WCYR7DQykLw TED Fellow Youtube-ID: UC6riU7xaRItrH_8_P6rYsfQ TED Institute Youtube-ID: UCV8cNYL6xPS-MxkQ2BTsX6Q TEDPrizeChannel Youtube-ID: UCDAdYdnCDt9zx3p3e_78lEQ TED Ideas Studio Youtube-ID: UC-yTB2bUcin9mmah36sXiYA TEDxYouth Youtube-ID: UCAuUUnT6oDeKwE6v1NGQxug TED

      1. DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG
      1. [Verse]Paul JohnsonDJ FunkDJ SneakDJ RushWax MasterHyperactiveJammin GeraldBrian WilsonGeorge ClintonLil LouisAshley BeedleNeil LandstrummKenny DopeDJ HellLouie VegaK-AlexiDr. Dre is in the house, yeahArmando in the houseGemini is in the houseJeff Mills is in the houseDJ DeeonDJ MiltonDJ SlugoDJs on the lowGreen VelvetJoey BeltramDJ ESPRoy DavisBoo WilliamsDJ TonkaDJ SkullDJ PierreMike Dearborn in the house, yeahTodd Edwards in the houseRomanthony in the houseCVO in the houseLuke SlaterDerrick CarterRobert HoodParris MitchellDave Clarke is in the houseVan Helden in the houseArmani in the houseSurgeon is in the house, yeah
      1. TEACHERS tracklist: Paul Johnson v. Jammin Gerald - CK's 'Partyin' with Paul' edit DJ Deeon 'Freak Mode II' intro DJ Deeon 'House-o-Matic' DJ Milton v. Thomas Bangalter 'Bang-o-Matics' CK edit Robert Armani v. Thomas Bangalter 'CK's Rollin' Up edit' Thomas Bangalter 'Spinal Beats' Cajmere / Dajae 'Brighter Days (Underground Goodies mix)' Paul Johnson 'Y'All Stole Them Dances' Gemini 'Le Fusion / Don't Stop' Paul Johnson / Robert Armani / Louis Bell/ Rick Garcia 'Mix It (CK's Baddest DJ edit)' DJ Deeon 'Freaks / Do-U-C' DJ Deeon 'In The House!' Robert Armani 'Ambulance' Gant-Man 'Gon' Bang Da Box' Thomas Bangalter v. George Kranz 'CK's Spinal Skranz edit' DJ Funk 'Work It!' Parris Mitchell Project feat. Waxmaster 'Ghetto Shout Out!' Daft Punk v. Waxmaster Teach that Body (CK's Chi-town edit)' DJ Slugo 'DJs on the Low'
      1. ```js import DOMPurify from 'dompurify'

        const App = () => { const data = lorem <b onmouseover="alert('mouseover');">ipsum</b> const sanitizedData = () => ({ __html: DOMPurify.sanitize(data) })

        return ( <div dangerouslySetInnerHTML={sanitizedData()} /> ); }

        export default App; ```

      1. It still doesn’t work - every component re-renders. This happens because we put items as a dependency for useCallback . Every time items update, useCallback returns a new reference of the function. This causes onChange prop to change, therefore updating every component in the list. To fix this, we need to stop relying on items as a dependency. We can achieve that with a functional state update:

        js const onChange = useCallback((id, value) => { setItems(prevItems => prevItems.map((item, index) => { return index !== id ? item : { value: value } })) }, []) // No dependencies

      2. To prevent that, we need to memoize it with useCallback. Let’s do that:

        ```js const Parent = () => { ...

        const onChange = useCallback((id, value) => { setItems(items.map((item, index) => { return index !== id ? item : { value: value } })) }, [items])

        return ( <div> {items.map((item, index) => ( <Item key={index} id={index} value={item.value} onChange={onChange} /> )} </div> ) } ```

      3. Anonymous functions will always get a new reference on every render. This means that onChange property will change every time Parent renders.

        js onChange={(id, value) => setState(state.map((item, index) => { return index !== id ? item : { value: value } })}

      4. If the component wrapped with memo re-renders, it means that one of its properties changes.
      5. If you don’t want a component to re-render when its parent renders, wrap it with memo. After that, the component indeed will only re-render when its props change.

        js const Item = memo(() => <div>Item</div>)

      1. showRSS tracks most TV shows, so you don't have to. RSS integration lets you automate your set up.
      1. Cyrus has the ability to export Usenet via IMAP and/or export shared IMAP mailboxes via NNTP.
    2. May 2022
      1. ```html

        Choose your monster's colors:

        <div> <input type="color" id="head" name="head" value="#e66465"> <label for="head">Head</label> </div> <div> <input type="color" id="body" name="body" value="#f6b73c"> <label for="body">Body</label> </div>

        ```

        ```js colorPicker.addEventListener("input", updateFirst, false); colorPicker.addEventListener("change", watchColorPicker, false);

        function watchColorPicker(event) { document.querySelectorAll("p").forEach(function(p) { p.style.color = event.target.value; }); } ```

      1. Following the newer definition, the aside element should be inside of the section element to which it is related. The main element is not a sectioning element (elements like article, section, body, figure etc. are). You can of course still place aside in main, but it will be related to the nearest sectioning element parent of main. That means there is no semantic difference (for aside) in these two examples:

        ```html

        <body> <main></main> <aside></aside> </body> <body> <main> <aside></aside> </main> </body>

        ```