Generate search links for comma separated words - javascript

as always, your help is very much valued <3
I have listings on my site that feature metadata keywords in the description. I'd like to make these appear like tags (our cms doesn't support tags hence this hack). It prints just the words separated with commas, like so:
<div class="tags">abp, accredited building practitioners, calendar of events, upcoming events</div>
Is javascript capable of finding any word in these divs and replacing them with a href that links to oursite.com/search?query=THEWORD ? If so, does anyone have a script they can share?

Here is a working function built with a little jQuery, although easily can be converted to basic JavaScript:
jQuery:
<script>
$(function(){
$('.tags').each(function(){
var obj=$(this),tags=obj.text().split(','),i=0,len=tags.length;
if(obj.text()) {
for(i;i<len;i++) {
var tag=tags[i].replace(/(^\s*)|(\s*$)/g,'');
tags[i]=''+tag+'';
}
obj.html(tags.join(', '));
}
});
});
</script>
HTML:
<div class="tags">abp, accredited building practitioners, calendar of events, upcoming events</div>
<div class="tags">test, another test, some more testing, etc</div>
<div class="tags">the, code, needed, to, be , in, an, each(), loop</div>
<div class="tags"></div>
<div class="tags">random, words, that, show, work, hopefully</div>
<div class="tags">the, return, false, was, causing, problems</div>
<div class="tags"></div>

**Check this out. If the alert msg that you see is what you are looking for than you just need to append it in the div.
http://jsfiddle.net/UH5U9/3/
EDIT
$('.tags').each(function(){
var s = $(this).html()
a = s.split(',');
var temp='';
for (var i = 0; i < a.length; i++)
{
temp =temp + ''+a[i]+'';
}
$(this).html('');
$(this).html(temp);
});

Related

Remove any specific html code using javascript

In the past I used Google Developer Console to delete some specific divs on a page. I could do it manually of course but in some cases where the divs where many I had to use the console. I had a single line code that did the job (I found it while searching the internet) but I lost my note.
So how can I delete using javascript any html code (by copy pasting the code).
Something like:
elements = $('<div ... </div>');
elements.remove();
OR
$('<div ... </div>').remove();
Any ideas? I am not an expert in javascript (obviously) and I've been searching stackoverflow for hours without finding anything that works.
UPDATE: I think some people might get confused with my question. Google developer console accepts javascript command lines. So even though I ask for javascript I will use the code on the google developer console.
UPDATE 2 :
Here is an example of a div I need to delete. Keep in mind I want to copy paste the entire code in the javascript code. Not just identify the div.
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
It's the data-entry-status="declined" that makes that div unique so I can't just identify the div using an id selector or a class selector. I need to put the entrire thing there and remove it.
I tried:
$('<div class="entry-status-overlay" data-entry-status="declined"><div class="entry-status-overlay__inner"><span class="entry-status-overlay__title">Declined</span></div></div>').remove();
It didn't remove the div.
Try to search the dom by its outerHTML.
function deleteDomByHtml(html){
html=html.replace(/\s/g,'');
$("*").each(function(){
if(this.outerHTML.replace(/\s/g,'')===html){
$(this).remove();
}
});
}
And try this line on this page:
deleteDomByHtml(`<span class="-img _glyph">Stack Overflow</span>`);
You cannot do by simply pasting the code. That will remove all the div element.
You may need a specific selector like id,class or child to specific parent to remove the element from the dom.
Consider this case the divs have common class but the data-entry-status is different. So you can get the dom using a selector and then check the dataset property.
For demo I have put it inside setTimeout to show the difference. In application you can avoid it
setTimeout(function() {
document.querySelectorAll('.entry-status-overlay').forEach(function(item) {
let getStatus = item.dataset.entryStatus;
if (getStatus === 'declined') {
item.remove()
}
})
}, 2000)
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div class="entry-status-overlay" data-entry-status="accepted">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">accepted</span>
</div>
</div>
Just add any attribute with [] and it will remove the element.
$('[class="entry-status-overlay"]').remove();
/*OR*/
$('[data-entry-status="declined"]').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
function del(){
var h = document.body.outerHTML;
h = h.match('<div>...</div>');
h.length--;
return h;
}
I guess this will work just give it a try... i tried on browser console and it worked, this way you can match the exact you want.
I might as well add my take on this. Try running this in your console and see the question vanish.
// convert the whole page into string
let thePage = document.body.innerHTML,
string = [].map.call( thePage, function(node){
return node.textContent || node.innerText || "";
}).join("");
// I get some string. in this scenario the Question or you can set one yourself
let replacableCode = document.getElementsByClassName('post-layout')[0].innerHTML,
string2 = [].map.call( replacableCode, function(node){
return node.textContent || node.innerText || "";
}).join("");
// replace whole page with the removed innerHTML string with blank
document.body.innerHTML = thePage.replace(replacableCode,'');
If you want to identify divs with that particular data attribute, you can use a data-attribute selector. In the example below, I've used a button and click event to make the demo more visual, but in the console the only line you'd need would be:
$('div[data-entry-status="declined"]').remove();
$(function() {
$("#testbutton").click(function() {
$('div[data-entry-status="declined"]').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div id="x">Some other div</div>
<button type="button" id="testbutton">Click me to test removing the div</button>
See https://api.jquery.com/category/selectors/attribute-selectors/ for documentation of attribute selectors.
P.S. Your idea to paste some raw HTML into the jQuery constructor and then execute "remove" on it cannot work - you're telling jQuery to create an object based on a HTML string, which is, as far as it's concerned, a new set of HTML. It does not try to match that to something existing on the page, even if that exact HTML is in the DOM somewhere, it pays it no attention. It treats what you just gave it as being totally independent. So then when you run .remove() on that new HTML...that HTML was never added to the page, so it cannot be removed. Therefore .remove() has no effect in that situation.

Make getElementsByClassName differ between 2 classes with the same name

I got a HTML page with two div/class elements with the same name, called "notifications". However, I want to count only the latter ones and dont count the first one.
The first one looks like this:
<a href="mynotifcations"><div class="notification">1</div>
This one should be excluded.
The later ones look like this:
<div class="notiheader"><span class="notification">2 notifications</span>
Right now I get the notification like this
document.getElementsByClassName("notification");
If I cycle through it, it returns "1" and then "2 notifications".
I would rather get merely the "2 notifications", or better yet just the number 2 as an integer.
How do I manage to do achieve that? I'm really running out of ideas :/
I would have to say that is a strange setup, but here is a way:
<script>
var special = document.querySelectorAll( "span.notification" );
alert (special[1].innerHTML);
</script>
It might be better to add a class to distinguish them (that's what they're for), but if you must, you can use document.querySelectorAll() to match the specific ones you're looking for:
document.querySelectorAll("div .notification")
This will only match divs with the notification class.
var elementsWanted = document.querySelectorAll("div .notification");
for(var i = 0; i < elementsWanted.length; i++){
elementsWanted[i].style.backgroundColor = "yellow";
}
<div class="notification">Span</div>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
<div class="notiheader"><span class="notification">Div</span>
Try this, here we first get all the notification classes, x.length gives the total no of notification classes in the html. Then do your stuff based on its index(zero based index).
function hookSecondNotification() {
var x = document.getElementsByClassName("notification")[1];
// x.style.backgroundColor = "red";
// here do your stuffs.
}

jquery fadeOut not working - update

i mean i wanna iterate manually using a for-loop or something. but this piece of code i came up with seems to be not working. i like combining javascript with jquery since jquery is not my cup of tea for major projects. i don't know much jquery either, i would say I'm beginning to learn, though. how do you iterate over a nodelist in jquery is the question i have for all those jquery fans this time. is it similar to the javascript way? anyway this is what i have come up with (the code of a beginner).
HERE'S THE CODE //not working
$(".sn").[0].fadeOut();
$(".sn").[0].fadeOut("slow");
$(".sn").[0].fadeOut(3000);
<div class="sn">
content
</div>
<div class="sn sn-2">
content
</div>
<div class="sn sn-3">
content
</div>
but $(".sn-2").fadeOut(); works like charm. why?
$('.sn').each(function(){
$(this).fadeOut('slow');
});
in your code, you're trying to fadeout the .sn div three times.
try the following:
$.each($('.sn'), function(i, obj) {
$('.sn:eq(' + i + ')').fadeOut(3000);
});
this way you'll be iterating over all the .sn class elements, and fade them out one by one by its index (:eq(i))
try this
$(".sn:first").fadeOut();
you can try this also :
for(var i=0; i < $(".sn").length; i+=1){
$(".sn").eq(i).fadeOut(3000);
}
Maybe you are looking for something like this?
It will fade out each sn element within a loop.
I also updated the html to make it more consistent
for(var i=0; i < $(".sn").length; i+=1){
$(".sn-"+[i]).fadeOut(3000);
}
HTML
<div class="sn sn-0"> content </div>
<div class="sn sn-1"> content </div>
<div class="sn sn-2"> content </div>
Further you need to know, that $(".sn") represents an object, which does not have any property [0] which you are trying to access with your code ($(".sn").[0])
So to make this work you have to access the element you want to trigger by any event like this $(".sn")[0].
Best

JS - Shouldn't this be written better? One function vs multiples?

I have a tweet stream where new tweets are added at the top and the older ones pushed down. You can click on the entire tweet and a panel slides down to reveal, "reply", "retweet", "favorite" etc. The panel is added to each new tweet added in the stream.
The code below works. Shouldn't this be better written so that only one call is being made? Or, as a new tweet is added. would I just have to add to the code with div#tc4, ul#tb4 etc?
$(document).ready(function () {
$("div#tc1").click(function () {
$("ul#tb1").slideToggle("fast");
});
$("div#tc2").click(function () {
$('ul#tb2').slideToggle("fast");
});
$("div#tc3").click(function () {
$('ul#tb3').slideToggle("fast");
});
});
Added Markup:
<div id="tc1" class="tweetcontainer">
<div class="avatarcontainer">
<div class="avatar"></div>
</div>
<div class="content">
<div class="tweetheader">
<div class="name">
<h1>John Drake</h1>
</div>
<div class="tweethandle">
<h2>#Drakejon</h2>
</div>
<div class="tweettime">10m</div>
</div>
<div>
<p>Exceptional Buys Ranger To Give Monitoring Shot In The Arm To Its 'DevOps' Platform http://tcrn.ch/11m3BrO by #sohear </p>
</div>
</div>
</div>
<!-------------Tool Bar -------------------------------->
<ul id="tb1" class="toolbar">
<li><a class="reply" href="#"><span>reply</span></a></li>
<li><a class="retweet" href="#"><span>retweet</span></a></li>
<li><a class="favorite" href="#"><span>favorite</span></a></li>
<li><a class="track" href="#"><span>track</span></a></li>
<li><a class="details" href="#"><span>details</span></a></li>
</ul>
I highly recommend separating your javascript from your detailed page function. The best way to do this is to put the retweeting panel inside the tweet container, then you don't even need to give it an id at all or encode in the javascript information about your html structure and ids. You can then just do:
$('.tweetcontainer').on('click', function(event) {
if ($(event.target).is(':descendantof(.toolbar)')) {
//ignore all clicks within the toolbar itself
return;
}
$(this).find('.toolbar').slideToggle();
});​
It's that easy! See it in action in a jsFiddle.
Now you can add as many tweet containers as you want to your page--and your javascript doesn't have to change one bit. Other solutions that require knowledge of specific ids linking to specific ids are suboptimal.
Note the descendantof pseudo-selector is custom (see the fiddle to find out how it works). Also, since you didn't provide any css, I had to choose some--it was quick so don't expect much. (Aww heck I just saw you updated your question to provide a jsFiddle with css giving a far prettier result--but I won't change mine now.) I did have to add a class to the actual tweet itself, but there is probably a better way to style it.
And if you want a click on the displayed toolbar itself (outside of a link) to allow collapsing the toolbar, change the code above to :descendantof(a).
If you don't want to change your page layout, another way to it is to encode the information about the linkage between html parts in the html itself using a data attribute. Change your tweetcontainer div to add a data attribute with a jQuery style selector in it that will properly locate the target:
<div class="tweetcontainer" data-target="#tb1">
You don't really have to remove the id if you use it elsewhere, but I wanted you to see that you don't need it any more. Then on document.ready:
$('.tweetcontainer').click(function () {
$($(this).data('target')).slideToggle('fast');
});
Here is another jsFiddle demonstrating this alternate technique (though it less elegant, in my opinion).
Last, I would like to mention that it seems possible you have a little bit of "div-itis". (We have all been there.) The toolbar anchor elements have unnecessary spans inside of them. The tweet name h1 element is inside a div, but could just be an h1 with class="name" instead.
In general, if there is only a single item inside a div and you can change your stylesheet to eliminate the div, then the div isn't needed. There are an awful lot of nested divs in your html, and I encourage you to remove as many of them as you can. Apply style to the other block elements you use and at least some, if not many, won't be needed.
I'd suggest (though currently untested):
$('div[id^="tc"]').click(function(){
var num = parseInt(this.id.replace(/\D+/g,''),10);
$('#tb' + num).slideToggle("fast");
});
Though given that you don't need the num to be a number (it'd be fine as a string), you could safely omit the parseInt().
Yes, you can write this code much more compactly like this:
$(document).ready(function() {
for (var i = 1; i < 3; i++) {
$("div#tc" + i).click(function() { $("ul#tb" + i).slideToggle("fast"); } );
}
});

How to swap two div tags?

I want to swap two html div tags entirely, tags and all. I tried the code below code but it does not work.
jQuery('#AllBlock-'+Id).insertAfter('#AllBlock-'+Id.next().next());
How to swap two div tags entirely.
You have some bracket mismatching in your code, it looks like you might be trying to do this:
jQuery('#AllBlock-'+Id).insertAfter($('#AllBlock-'+Id').next().next());
Which would take something like:
<div id="AllBlock-5"></div>
<div id="AllBlock-6"></div>
<div id="AllBlock-7"></div>
And, if called with Id 5, turn it into this:
<div id="AllBlock-6"></div>
<div id="AllBlock-7"></div>
<div id="AllBlock-5"></div>
This is because you're taking block 5, and moving it (using insertAfter) to the place after the block that's next().next() (or next-but-one) from itself, which would be block 7.
If you want to always swap #AllBlock-Id with #AllBlock-[Id+2], so they switch places and end up like the following:
<div id="AllBlock-7"></div>
<div id="AllBlock-6"></div>
<div id="AllBlock-5"></div>
You might want to try:
var $block = jQuery('#AllBlock-'+Id);
var $pivot = $block.next();
var $blockToSwap = $pivot.next();
$blockToSwap.insertBefore($pivot);
$block.insertAfter($pivot);
You can't do this because you can't concatenate a string and a jQuery object.
Try this:
var div = $('#AllBlock-'+Id);
div.insertAfter(div.next().next());
it should be like this
you should close the bracket after Id,
jQuery('#AllBlock-'+Id).insertAfter('#AllBlock-'+Id).next().next());
You'll need to detach the existing dom object first, then re-use it later:
$('#divid').detach().insertAfter('#someotherdivid');
What I understand is you want to swap a div when clicked with the last div. What will you do if it is the last div? move it to the top?
This solution should solve the problem, furthermore, you can modify this regex to match the format of your ID. This can probably be made more concise and robust. For example, you could get the last ID a bit more sophisticatedly. This may just be modifying the selector or something more. I mean, you do not want to go rearranging the footer or something just because its the last div on the page.
$('div').click(function() {
//set regex
var re = /(^\w+-)(\d+)$/i;
//get attr broken into parts
var str = $(this).attr('id').match(re)[1],
id = $(this).attr('id').match(re)[2];
//get div count and bulid last id
var lastStr = $('div:last').attr('id').match(re)[1],
lastID = $('div:last').attr('id').match(re)[2];
//if we have any div but the last, swap it with the end
if ( id !== lastID ) {
$(this).insertAfter('#'+lastStr+lastID);
}
//otherwise, move the last one to the top of the stack
else {
$(this).insertBefore('div:first');
} });
Check out this working fiddle: http://jsfiddle.net/sQYhD/
You may also be interested in the jquery-ui library: http://jqueryui.com/demos/sortable/

Categories