Linkify (plain url to link) based on windowSize

Discussion in 'jQuery' started by 7643sfsag6, Jul 2, 2018.

  1. #1
    Hi all,
    this is what i would like to do
    1. when window size is < 1000, change any plain text url to a clickable one
    2. when window size is > 1000, change any plain text url to a clickable one, replaced by the word "Link".
    I had a go but it seems to be failing somewhere!
    Anyone can shed some light?
    Thanks

    HTML
    <html>
    <head>
       <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
       <script>$(document).ready(function() {
        function checkWidth() {
            var windowSize = $(window).width();
            if (windowSize < 1000) {
              $('div').each(function(){ $(this).html( $(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a href="$1">$1</a> ') ); });
            } //make plain text url clickable
            else if (windowSize < 1000) {
              $('div').each(function(){ $(this).html( $(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a href="Link">Link</a> ') ); });
            } //convert plain text to clickable word "Link"
          
        }
        checkWidth();
        $(window).resize(checkWidth);
        $(window).onload(checkWidth);
    });
      </script>
    </head>
    <body>
      <div>https://www.google.com/</div>
      <div>https://www.yahoo.com/</div>
      </body>
    </html>
    HTML:

     
    7643sfsag6, Jul 2, 2018 IP
  2. 7643sfsag6

    7643sfsag6 Member

    Messages:
    58
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    43
    #2
    Nice solution from @jakecigar in the jquery forums

    HTML:
    <div>https://www.google.com/</div>
    <div>https://www.yahoo.com/</div>
    HTML:
    CSS:
    @media only screen and (max-width: 1000px) {
      .abbr {
       font-size:0;
        text-decoration:none;
      }
      .abbr:after {
        display: inline;
        font-size:16px;
        content: "link";
        color:black;
      }
    }
    Code (CSS):
    JS:
    $(function() {
      $('div').each(function() {
        $(this).html($(this).html().replace(/((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, '<a class=abbr href="$1">$1</a> '));
      });
    })
    Code (JavaScript):
     
    7643sfsag6, Jul 3, 2018 IP
  3. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #3
    There are a LOT of problems with that code -- to be expected with the train wreck of mental enfeeblement that is jQuery. On top of the obvious one of derping into the live DOM with innerHTML forcing a reparse of the ENTIRE page, you have that it will actually intercept EXISTING anchors screwing with them if present in your target DIV. It also parses the ENTIRE HTML of the child instead of just isolating textNodes within it, and really that's what the ideal should be.

    This is the trap of the 'false simplicity' jQuery dupes people into, as it makes it 'so simple' to utterly cock up... so let's kick jQuery to the curb, use a document fragment to do parsing of just textNodes, and walk the DOM to get said nodes using DOM methodology to do the work!

    You would call the autoLinker.parse method of this object to run it. autoLinker.htmlParse is an internal to turn the replaced markup into a DOM structure OFF the live DOM where it can be done faster with a smaller memory footprint instead of derping it into the live page!

    
    var autoLinker = {
    	htmlParse : function(code) {
    		var body = document.implementation.createHTMLDocument('').body;
    		body.innerHTML = code;
    		return body;
    	},
    	parse : function(e) {
    		if ((e.nodeType != 1) || !e.firstChild) return;
    		switch (e.tagName.toLowerCase()) {
    			case 'a':
    			case 'script':
    			case 'style':
    				return;
    		}
    		e = e.firstChild;
    		do switch (e.nodeType) {
    			case 3 :
    				var
    					replace = e.nodeValue.replace(this.uriRegex, this.uriReplace),
    					walk;
    				if (
    					(replace !== e.nodeValue) &&
    					(walk = this.htmlParse(replace).firstChild)
    				) {
    					// and people say you can't replace a textnode with multiple DOM elements
    					do {
    						e.parentNode.insertBefore(walk.cloneNode(true), e);
    					} while (walk = walk.nextSibling);
    					e.parentNode.removeChild(e);
    				}
    				break;
    			case 1:
    				this.parse(e);
    		} while (e = e.nextSibling);
    	},
    	uriRegex : /((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g,
    	uriReplace : '<a class="autoLinked" href="$1">$1</a>'
    }
    
    Code (markup):
    Mind you this wouldn't auto-apply to just your DIV, you'd have to implement that -- but it's now safe to apply it to the entire document body!

    
    autoLinker.parse(document.body);
    
    Code (markup):
    Which is a vast improvement. jQuery -- even when it 'saves' you code, it really doesn't... Laugh is this might even run faster. It's even XML safe and could be used on elements not even attached to the document yet.

    Another improvement might be to add a check to make sure no parentNode in the tree is an anchor, but that might be overkill... still you might not want to trap existing textnodes that match if they're already a link.

    -- edit -- uploaded better version including blockout for anchors.
     
    Last edited: Jul 3, 2018
    deathshadow, Jul 3, 2018 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #4
    deathshadow, Jul 3, 2018 IP