Welcome to WebmasterWorld Guest from 3.80.60.248

Forum Moderators: open

Message Too Old, No Replies

Writing the URL to a share link

     
6:20 pm on Nov 2, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


I'm still learning so please be gentle.

I'm trying to add the URL to be shared via the various social media sharer links, which I can then add to each page without coding each URL separately for every sharer link.

I thought this would be a good first project, but half a day later I'm still not getting it working.

This is what I've got so far:
<a href="javascript: document.write('http://www.linkedin.com/shareArticle?mini=true&amp;url=' + location.href);"
title="Share this page on LinkedIn">Share</a>


Any suggestions or pointers for reading? When I get it working it'll be much more lightweight than the sharing widgets. Thanks!
7:42 pm on Nov 2, 2014 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month

joined:Mar 9, 2003
posts:2099
votes: 8


There are many others on WebmasterWorld who are much more accomplished at Javascript than I am, but after a couple of months this is the kind of thing that I expect myself to be able to do (nearly) off the top of my head by now.

So I'm going to have a go and try to help you out as best as I can and then (no doubt) a WW member more experienced at front-end scripting than I will be able to show you what else you need to do.

Step One
The first thing you need to do is change the inline javascript into unobtrusive javascript (so you can separate structure and function - just as you would separate structure and style with external CSS). To do this, you will need a way to navigate the DOM and identify the <a[nchors]> in question.

Assuming you have something like the following in your markup:


<ul class="sharing">
<li id="facebook">...</li>
<li id="linkedin"><a href="#">Share on LinkedIn</a></li>
<li id="twitter">...</li>
</ul>


You can identify the link like this:


document.getElementById('linkedin').getElementsByTagName('a')[0]


Step Two
Knowing that, you can then set the href property of the identified link like this:

function setLinkDestinations() {
document.getElementById('linkedin').getElementsByTagName('a')[0].setAttribute('href','http://www.linkedin.com/shareArticle?mini=true&amp;url=' + location.href);}


That ought to work for one link.

Step Three
What you now need is an array:


var sharingNetworks = ['facebook', 'linkedin', 'twitter'];


and an object containing the link format for each sharing network:


var sharingNetworkLinks = {facebook:'URL here', linkedin:'http://www.linkedin.com/shareArticle?mini=true&amp;url=', twitter:'URL here'};


Then, in the setLinkDestinations function (above) you can loop through the sharingNetworks array and on each loop, add each sharingNetworks element to the next

getElementById('')


and, additionally, add the respective link destination (from the sharingNetworkLinks object) to the appropriate link.

[edited by: ronin at 8:18 pm (utc) on Nov 2, 2014]

8:06 pm on Nov 2, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Wow, thanks.

This looks way more complicated that I was expecting!

I was trying to keep everything inline intentionally, as there are only 2 sharing links and it seems simpler and tidier that way.

Is it easier to do this inline, without an array?

Or just duplicating the code above? Eg:
function setLinkDestinations() {
document.getElementById('linkedin').getElementsByTagName('a')[0].setAttribute('href','http://www.linkedin.com/shareArticle?mini=true&amp;url=' + location.href);}
{
document.getElementById('facebook').getElementsByTagName('a')[0].setAttribute('href','http://www.facebook.com/sharer.php?u=' + location.href);}
8:14 pm on Nov 2, 2014 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month

joined:Mar 9, 2003
posts:2099
votes: 8


Umm... I'm going to hand the baton over to someone else now. Javascript is something I am (very much) stil learning and, as I say, there are many members here on WW who know their way around .js a lot better than I do...!
8:17 pm on Nov 2, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Thanks Ronin for your help - some of the code you used is useful to get me on the right path with a bit of googling
2:58 pm on Nov 3, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24



change the inline javascript into unobtrusive javascript (so you can separate structure and function

A good first suggestion. Keeping a clean separation of content and behavior makes it easier to maintain.

I was trying to keep everything inline intentionally, as there are only 2 sharing links and it seems simpler and tidier that way.

It's really not. It adds weight to your HTML code that can't be cached. Generally speaking, you should put all of your JavaScript code in one (or more, depending on what it is) separate JavaScript file. Browsers can cache those files. It also makes it easier to maintain because to modify behavior, you make changes to the JavaScript file (as opposed to sift through content to find where you need to make changes).
Also, you may only have 2 sharing links right now, but you may want to add more in the future.

Here's how I'd start. If you're going to do this client side, then you'll only want to show the links if the client has JavaScript enabled. This is Progressive Enhancement. So by default, your content should NOT include links. You can, however, include an empty placeholder where the links will go.


<div class="share-links"></div>


Next, you'll want some JavaScript code that finds this placeholder, and inserts content into it:


(function () {
var i,
n,
placeholders;

try {
placeholders = document.getElementsByClassName('share-links');
}
catch (e) {
// getElementsByClassName is not supported by IE <= 8
// You can add a polyfill for those obsolete versions if you need it
return;
}

function appendLinks(el) {
// append links to el
}

for (i = 0, n = placeholders.length; i < n; i++) {
appendLinks(placeholders[i]);
}
})();


Next, lets modify that appendLinks method to actually append some content:

function createLinkedInShareLink() {
var el = document.createElement('a');
el.href = 'http://www.linkedin.com/shareArticle?mini=true&amp;url=' + encodeURIComponent(location.href);
el.title = 'Share this page on LinkedIn';
el.appendChild(document.createTextNode('Share'));
return el;
}

function appendLinks(el) {
// append links to el
el.appendChild(createLinkedInShareLink());
}


Now you've got some nice modular code that you can easily add to and maintain. For example, if LinkedIn changes the way the URL has to be formed, you can just modify the createLinkedInShareLink method. And if you want to create a Facebook or Twitter link, you can create another function named "createFacebookShareLink" or "createTwitterShareLink" respectively, which creates the appropriate link element, and then in appendLinks you'd add el.appendChild(createFacebookShareLink()), and so on.

The other benefit to doing it this way is that anywhere you want to put the links, you just need to add another placeholder container (and you can have as many as you want).

Note also, I added the encodeURIComponent to property encode the location.href.

Hope this works for you. Here is the entire JavaScript:

(function () {
var i,
n,
placeholders;

try {
placeholders = document.getElementsByClassName('share-links');
}
catch (e) {
// getElementsByClassName is not supported by IE <= 8
// You can add a polyfill for those obsolete versions if you need it
return;
}

function createLinkedInShareLink() {
var el = document.createElement('a');
el.href = 'http://www.linkedin.com/shareArticle?mini=true&amp;url=' + encodeURIComponent(location.href);
el.title = 'Share this page on LinkedIn';
el.appendChild(document.createTextNode('Share'));
return el;
}

function appendLinks(el) {
// append links to el
el.appendChild(createLinkedInShareLink());
}

for (i = 0, n = placeholders.length; i < n; i++) {
appendLinks(placeholders[i]);
}
})();
3:03 pm on Nov 3, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24


One thing I forgot to mention...
This code should be placed AFTER all of your <div class="share-links"></div> containers, preferably just before the closing </body> tag. That's to ensure that the DOM is complete and all of the "share-links" containers can be found by document.getElementsByClassName.
3:49 pm on Nov 3, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Fotiman, impressive, I'll try that out!

It reminds me a bit of the Dynamic Site bookmarks script, which I'm trying to hack with a bit to learn.

Would it not be better to use getElementsById? Or is this do with the 2 different services?

The reason I started with this in the first place was because I did something similar on my blog, which was simple with php and wordpress.

So I decided to try this out on my static site, and after figuring out that I could tag the page name to help with event tracking:

_paq.push(['trackEvent','Newsletter','Subscribe',location.pathname.substring(1)])


I thought it would be great to do something similar with the sharing links and how they append the URL.

I agree with putting it in an external file and consolidating them, and I'm comfortable with doing that with CSS, but with jquery, a bookmark js and now this file I don't think my skills are up to consolidating them into 1 yet.
3:57 pm on Nov 3, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24



Would it not be better to use getElementsById? Or is this do with the 2 different services?

There is not such thing as getElementsById, but there *is* a getElementById. The problem with that approach is that IDs need to be unique. Using class names instead allows you to have multiple copies on the same page without having to do anything special to handle it. Using the class name makes it a little easier to be portable to other pages as well.

The code I provided above uses plain JavaScript. If you have jQuery, it can be simplified even further. :)
4:10 pm on Nov 3, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


I started fiddling with it from that bookmarks script, and when I saw that getElementsByClassName wasn't supported by IE<8 I thought it might work better, but getElementById seems to have the same problem...

My limit at the moment with jquery is sticky boxes! Hopefully in a few months I'll be able to apply it to rewriting this code.

Thanks again
4:22 pm on Nov 3, 2014 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month

joined:Mar 9, 2003
posts:2099
votes: 8


My thanks to Fotiman too.

As a javascript aspirant with only a few months experience, it is a valuable exercise to be faced with a challenge, try to complete it as best one can and then see how a pro would tackle it.

I was very much hoping that someone would step in and show how it's really done and very glad you did, Fotiman - thanks!
5:26 pm on Nov 3, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24



when I saw that getElementsByClassName wasn't supported by IE<8 I thought it might work better, but getElementById seems to have the same problem...

getElementById is supported by older versions of IE, so you *could* modify this to use getElementById instead if you wanted to. But doing so would be a change in the general logic. The getElementsByClassName approach is more of a "apply this to one or more elements that match this class" approach, whereas the getElementById approach would need to be more of a "apply this to exactly the one element that matches this ID" approach... it's just a much more restrictive approach to use IDs.

As for a jQuery approach, this can be helpful for avoiding the issue with getElementsByClassname, as jQuery's selector language already handles classnames. The code above could be written in a much more terse way with jQuery like this:


(function () {
$('.share-links').each(function () {
$(this).append(createLinkedInShareLink())
.append(" ")
.append(createFacebookShareLink());
});

function createLinkedInShareLink() {
return $("<a />", {
href: 'http://www.linkedin.com/shareArticle?mini=true&amp;url=' + encodeURIComponent(location.href),
title: 'Share this page on LinkedIn',
text: 'Share'
});
}

function createFacebookShareLink() {
return $("<a />", {
href: 'http://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(location.href),
title: 'Share this page on Facebook',
text: 'Share on Facebook'
});
}
})();


Note, I still kept the methods for creating the individual link elements separate in order to better facilitate adding additional links, and I included a way to add a Facebook link as well, just to show how simple and maintainable it can be.
:)
8:39 pm on Nov 3, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Above and beyond Fotiman!

I have jquery included already at the bottom of the page - does this code go in a separate file that's then included after?

It doesn't go in the same jquery file I assume?

I'm thinking that this would also be great for a simple tell a friend link with mailto - would this work? For example:

function createEmailShareLink() {
return $("<a />", {
href: mailto:?subject=Check%20this%20out%20&amp;body=url=' + encodeURIComponent(location.href),
title: 'Click to email this to a friend',
text: 'Tell a friend'
});
}
8:41 pm on Nov 3, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Oops: body=' + encodeURIComponent(location.href),
8:47 pm on Nov 3, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


Thinking ahead, for the event tracking I can just add the onclick to the outer share-links div.

But to add target="_blank", is 'target' recognised in this code:
function createLinkedInShareLink() {
return $("<a />", {
href: 'http://www.linkedin.com/shareArticle?mini=true&amp;url=' + encodeURIComponent(location.href),
title: 'Share this page on LinkedIn',
text: 'Share'
target: '_blank'
});
}


It's quite the script we've got here!
10:24 pm on Nov 3, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24


I have jquery included already at the bottom of the page - does this code go in a separate file that's then included after?

I would keep 3rd party library code (like jQuery) separate, so that if you ever decide to upgrade it to a newer version, you don't lose your own changes (plus each library may have it's own embedded copyright statement, etc.). So instead, something more like this:

<script src="jQuery.js"></script>
<script src="site.js"></script>
</body>
</html>



this would also be great for a simple tell a friend link with mailto - would this work?


You forgot an opening quote in the value of the href (before mailto), but I think that would work (assuming they were using a mail client that understands the body= part... I seem to recall something about not not all email clients handling that, but that was years ago).

Thinking ahead, for the event tracking I can just add the onclick to the outer share-links div

True, you could attach an event handler to the outer share-links div, or add the target attribute as you did (yes, that would work, but you forgot a comma after the text: 'Share').
9:10 pm on Nov 4, 2014 (gmt 0)

Junior Member

10+ Year Member

joined:Aug 19, 2006
posts: 169
votes: 0


I've been fiddling with this today and it's going great.

I've used the original version as I didn't want to create a dependency on jquery, also because it's not always loaded.

I've got the target _blank ok and I'm working on adding a class, but I think there's something I'm missing to get this to work - all the divs show up as LinkedIn share links.

How do we get the script to create 1 LinkedIn, 1 Facebook, 1 email a friend, etc. It would need a second class attribute, or an id?

Is that what 'this' refers to here
$(this).append(createLinkedInShareLink())


So it would be 'share-link this' for 1 div, 'share-link that' for another, and then
$(this).append(createLinkedInShareLink())
$(that).append(createFacebookShareLink())


Am I on the right track?
9:34 pm on Nov 4, 2014 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member fotiman is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Oct 17, 2005
posts: 5019
votes: 24


How do we get the script to create 1 LinkedIn, 1 Facebook, 1 email a friend, etc.

You would add those additional links to your appendLinks function. For example:

function appendLinks(el) {
// append links to el
el.appendChild(createLinkedInShareLink());
el.appendChild(createWhiteSpace());
el.appendChild(createFacebookShareLink());
}

Note, I added a "createWhiteSpace" method which would be used just to create a text node with a blank space between the links.

Is that what 'this' refers to here
$(this).append(createLinkedInShareLink())

"this" in the jQuery example was referring to the container with the class "share-links".


So it would be 'share-link this' for 1 div, 'share-link that' for another, and then
$(this).append(createLinkedInShareLink())
$(that).append(createFacebookShareLink())

Am I on the right track?

Well, for one that's using the jQuery approach (which you just said you were not using), so I'm confused as to what you're trying to do. :) With that said, the goal would be that you have a container (<div class="share-links"></div>) that contains all of the links. The intention was not that you'd create separate containers for each of the individual link types, but rather that all of the share links would be appended to the share-links.

Make sense?
 

Join The Conversation

Moderators and Top Contributors

Hot Threads This Week

Featured Threads

Free SEO Tools

Hire Expert Members