Search code examples
jqueryarrayshrefreplacewith

jQuery replaceWith() - re-using the removed values


I'm using jQuery to de-dupe identical links that are close together, for keyboard users. I still want mouse users to be able to click the 'more' link if they want, so I'm putting the link back on hover.

What I've done is working, but it seems like a bit of a palaver. I read in the Jquery api that replaceWith() returns the replaced values, but where's it keeping them? How can I get them back when needed?

I understood that the original values go into some sort of array. It looks like it should be possible to create a named array in the first function, then access its correct values in the second. I'm really bad with arrays & will welcome any assistance.

jQuery(function ($) {

// dedupe links in post list widgets

	    $( ".widget li" ).each(function( i ) {
			var firstA = $(this).children( 'a:first-child' );
			var myH = $( firstA ).attr( 'href' );
			var dupeA =	$( firstA ).siblings( 'a' );
			var dupeH = $( dupeA ).attr( 'href' );
			if( dupeH == myH ) { 
				$( dupeA ).replaceWith( '<span class="more-link">Open</span>' );
			}
    });
	
// replace link if needed

		$( '.widget li' ).hover(function( i ) {
			var myH = $(this).children( 'a:first-child' ).attr( 'href' );
			$(this).children( 'span.more-link' ).replaceWith( '<a href="' + myH + '" class="more-link">Open</a>' ).addClass( 'hover' );
		});
   
});
ul {
    list-style-type: none;
}
li, li > * {
    float: left;
    clear: left;
    display: block;
}
li {
    padding-bottom: 1em;
}
li a:first-child ~ * {
    padding-left: 1em;
}
.more-link {
    border: 1px solid red;
    padding: .3em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="widget">
	<ul class="index-widget">
		<li>
			<a href="https://stackoverflow.com">Stack Overflow</a>
			<time>14 May 2018</time>
			<span class="index-excerpt">Answers questions</span>
			<a href="https://stackoverflow.com" class="more-link">Open</a>
		</li>
		<li>
			<a href="https://jquery.com">jQuery</a> 
			<time>15 May 2018</time>
			<span class="index-excerpt">Prompts questions</span>
			<a href="https://jquery.com" class="more-link">Open</a>
		</li>
	</ul>
</div>
</body>

Further edit: Code on here now. Thanks, zer00ne.


Solution

  • You just need to get the returning value of the replaceWith function so you could reuse it later.

    For example:

    var replaced = $( dupeA ).replaceWith( '<span class="more-link">Open</span>' );
    

    replaced will then be a reference to the replaced dupeA element. So later you could just simply do:

    $(this).children( 'span.more-link' ).replaceWith( replaced );
    

    to put dopeA back on.

    You will be aware of the scope of the variables to be able of using replaced in the place you need it. In you example you would need to have replaced defined as a global variable or defined in the scope where both event functions are binded (main executed function).

    More info about replaceWith function can be found here.

    Hope it helps!

    Edit I've applied the function to your case, with minor improvements.

    jQuery(function ($) {
    	$('.widget li').each(function(i, e) {
    		var firstA = $(this).children('a:first-child');
    		var myH = $(firstA).attr('href');
    		var dupeA =	$(firstA).siblings('a');
    		var dupeH = $(dupeA).attr('href');
    		var replaced = false; // Set a variable to check if the item has been replaced
    		var repA; // Stored the replaced item
    		if(dupeH == myH) {
          // Replaces the item and stores the item in a variable
    			repA = $(dupeA).replaceWith($('<span class="more-link">Open [replaced]</span>'));
          // Only if replaced, the mouseneter event is set
    			$(e).mouseenter(function() {
            // If the element has not been replaced yet
    				if(replaced === false) {
    					// Sets the element as replaced
              replaced = true;
              // Put back the replaced element
    					$(this).children('span.more-link').replaceWith(repA.addClass('hover'));
    				}
    			});
    		}
        });
    });
    ul {
        list-style-type: none;
    }
    li, li > * {
        float: left;
        clear: left;
        display: block;
    }
    li {
        padding-bottom: 1em;
    }
    li a:first-child ~ * {
        padding-left: 1em;
    }
    .more-link {
        border: 1px solid red;
        padding: .3em;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <body>
    <div class="widget">
    	<ul class="index-widget">
    		<li>
    			<a href="https://stackoverflow.com">Stack Overflow</a>
    			<time>14 May 2018</time>
    			<span class="index-excerpt">Answers questions</span>
    			<a href="https://stackoverflow.com" class="more-link">Open</a>
    		</li>
    		<li>
    			<a href="https://jquery.com">jQuery</a> 
    			<time>15 May 2018</time>
    			<span class="index-excerpt">Prompts questions</span>
    			<a href="https://jquery.com" class="more-link">Open</a>
    		</li>
    	</ul>
    </div>
    </body>