Кнопки социальных сетей, HTML 5, атрибут data и асинхронная загрузка javascript

Давно уже планировал установить на свой сайт кнопки социальных сетей. Наконец нашел время для этого, проблема усугублялась тем, что я сам не являюсь пользователем социальных сетей, хотя против ничего не имею.

Первым делом начал собирать информацию, ее довольно много, есть правда и устаревшая. Например, Twitter поменял уже ссылку, старая twitter.com/share, а новая twitter.com/intent/tweet, у Google ссылка «www.google.com/buzz/post», уже давно не работает, вместо нее plus.google.com/share. Конечно, это общеизвестные факты, но, похоже, все-таки не все об этом знают и предлагают «шарить» на старые ссылки.

В общем, ознакомившись с темой, решил взять кнопки в первоисточнике:
Twitter — twitter.com/about/resources/buttons
Facebook — developers.facebook.com/docs/reference/plugins/like
Vkontakte — vk.com/developers.php?o=-1&p=Like
Google+ — developers.google.com/+/plugins/+1button

Получил я коды кнопок, причем пришлось, немного повозится, что бы получит кнопки хотя бы одной высоты, я ведь их в блок решил объединить, а для этого лучше бы они были одного размера.

Twitter:
<a href="https://twitter.com/share" class="twitter-share-button" data-lang="ru">Твитнуть</a>

<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>


Facebook:

<div id="fb-root"></div>

<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/ru_RU/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>


Google+:

<!-- Place this tag where you want the +1 button to render. -->
<div class="g-plusone" data-annotation="none"></div>


<!-- Place this tag after the last +1 button tag. -->
<script type="text/javascript">
  window.___gcfg = {lang: 'ru'};

  (function() {
    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
    po.src = 'https://apis.google.com/js/plusone.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
  })();
</script>


Vkontakte:

<!-- Put this script tag to the <head> of your page -->
<script type="text/javascript" src="//vk.com/js/api/openapi.js?75"></script>

<script type="text/javascript">
  VK.init({apiId: 3363525, onlyWidgets: true});
</script>

<!-- Put this div tag to the place, where the Like block will be -->
<div id="vk_like"></div>

<script type="text/javascript">
VK.Widgets.Like("vk_like", {type: "button"});
</script>


Вот такие коды кнопок. Что же мы видим? Vkontakte единственный из представленных кодов, не использует HTML 5. В данном случае на использование HTML 5 указывает атрибут data- в html тегах. Еще интересно, что у Twitter и Facebook очень похожие коды, видимо, подсматривают друг у друга. Еще у Twitter и Facebook не указан type=«text/javascript», что соответствует HTML5, атрибут type теперь не является обязательным. Значение по умолчанию JavaScript (ECMAScript). А Google продолжает указывать type=«text/javascript». Зато Google единственный кто использует асинхронную загрузку javascript, при помощи атрибута async, соответствующего спецификации HTML 5.

Об асинхронной загрузке скриптов стоит сказать немного больше. В Google молодцы, что используют асинхронную загрузку скрипта, а другие зря пренебрегают такой возможностью. Что же такое эта асинхронная загрузка, все просто, это указание браузеру загрузить скрипт, как только будет возможность его загрузить, а если пока нет возможности, браузер продолжит работать дальше.

Для чего это нужно? Например, Вы поставили на свой сайт кнопку «Твитнуть», а мы помним, что у них нет в коде атрибута async. И все бы хорошо, но у многих на работе закрыт доступ к социальным сетям и когда к Вам на сайт зайдет пользователь без доступа к Twittter его браузер не сможет загрузить скрипты с Твиттера, а т.к. загрузка синхронная браузер заметно «подвиснет», пока попытка загрузить скрипт не прекратится по таймауту.

Как это касается Вас? Не каждый пользователь будет ждать загрузки Вашего сайта, а если дождется в дальнейшем, может, не вернутся, зачем ему возвращаться на «тормозной» сайт. Делаем вывод, что в ряде случаев асинхронная загрузка скриптов — нужная вещь.

В связи с тем, что полученные кнопки я решил объединить в один блок, логично будет весь javascript код также объединить в один скрипт и добавить асинхронную загрузку. Кроме того, я пока не использую HTML 5 на своем сайте и для того, что бы код был валидным, все атрибуты HTML 5 нужно установить с помощью javascript.

С помощью javascript, атрибут data- устанавливается очень просто, например:

<div class="g-plusone" data-annotation="none"></div>

==

document.getElementById(id).dataset.annotation = "none"


Как всегда не обошлось без нюансов. Работает во всех браузерах, кроме… Как Вы уже догадались, кроме IE до ie8, в ie9 уже работает. Но мы запишем по-другому, что бы работало во всех браузерах:

document.getElementById(id).setAttribute("data-annotation", "none"); 


В конечном итоге вот, что у меня получилось:

1. Немного изменил HTML, главным образом мне на сайте совсем не нужна прямая ссылка на Twitter, а в своем коде они проставляют такую ссылку: Твитнуть, зачем им это не понятно, что о них кто-то еще не знает? Или рейтинг в поисковиках маленький? В общем, записал так: Твитнуть, можно, конечно rel=«nofollow» поставить, но я выбрал максимально кардинальный метод. Вообще бы убрал тег «А», но без него не работает. HTML блок кнопок, вставляем туда, где хотим увидеть кнопки:

<ul style="height:40px;list-style:none;margin:0;padding:0;">
	<li style="float:left;">
		<a id="s-twitter" class="twitter-share-button"> </a></li>
	<li style="float:left;">
		<div id="s-facebook" class="fb-like" style="margin-right:40px;">
			 </div>
	</li>
	<li style="float:left;">
		<div id="vk_like">
			 </div>
	</li>
	<li style="float:left;margin-right:10px;">
		<div id="s-google" class="g-plusone">
			 </div>
	</li>
</ul>


2. Javascript код асинхронной загрузки скриптов для кнопок, вставляйте куда хотите, обычно или в head или в конец страницы. Кстати у Twitter и Facebook в коде есть защита от повторной загрузки скриптов, сделанная, на случай если код вставить в страницу несколько раз, не думаю, что мой код кто-то вставит несколько раз, но на всякий случай защиту от повторной загрузки скриптов я оставил:

<script type="text/javascript">
(function() {
	function async_load(u,id) {
		if (!gid(id)) {
			s="script", d=document,
			o = d.createElement(s);
			o.type = 'text/javascript';
                        o.id = id;
			o.async = true;
			o.src = u;
			// Creating scripts on page
			x = d.getElementsByTagName(s)[0];
			x.parentNode.insertBefore(o,x);
		}
	}
	function gid (id){
		return document.getElementById(id);
	}
	window.onload = function() {
	
	e = gid("s-twitter");
	e.setAttribute("data-lang", "ru"); 
	
	e = gid("s-facebook");
	e.setAttribute("data-layout", "button_count"); 
	e.setAttribute("data-send", "false"); 
	
	e = gid("s-google");
	e.setAttribute("data-size", "medium"); 
	
	
	async_load("//platform.twitter.com/widgets.js", "id-twitter");//twitter
	async_load("//connect.facebook.net/ru_RU/all.js#xfbml=1", "id-facebook");//facebook
	async_load("https://apis.google.com/js/plusone.js", "id-google");//google
	async_load("//vk.com/js/api/openapi.js", "id-vkontakte");//vkontakte
	};
	// Инициализация vkontakte
	window.vkAsyncInit = function(){
		VK.init({apiId: 3363525, onlyWidgets: true});
		VK.Widgets.Like("vk_like", {type: "button", height: 20});
	};
})();
</script>


Последний нюанс, Вам придется зарегистрировать свой сайт vkontakte, что бы получить apiId, можете оставить мой apiId, но только на Вашем сайте он работать не будет.

Удачи!
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 28
  • +3
    Для полного восторга не хватает демочки.
    Используйте и сделайте пожалуйста демку.
    • +2
      К сожалению на указанном ресурсе код работать не будет, и на локальном компьютере работать не будет!
      Вернее код отработает как надо, только Вы ничего не увидите, этот код загружает сторонние скрипты, с twitter, facebook, google, vkontakte, а вот они четко отслеживают запуск и запускаются только на реальном хостинге. Эти кнопочки, именно с этим кодом, работают на одном сайта, но к сожалению по правилам я не могу указать на него ссылку.

      Кстати, это очень важный момент, что код работает только на реальном Интернет хостинге.

      А вообще цель статьи была рассказать об асинхронной загрузке javascript (это можно и в своих проектах использовать — грузить скрипты асинхронно) и кроссбраузерном указании атрибута data-, с помощью javascript.
    • +2
      У Артёма Сапегина есть отличный плагин по этой теме.
      • +2
        Вероятнее всего отличных плагинов много, социальные кнопки уже давно придумали.
      • –1
        А давно атрибут data- это html5?
        • +6
          Конечно, я бы мог ответить просто написав «Давно», Как говорится: «какой вопрос — такой ответ».

          Но, что бы не осталось сомнений попробую раскрыть и эту тему. Возможно проще было бы дать ссылку на спецификацию, но мы пойдем другим путем. Возьмем малюсенький код, главное, что он будет с атрибутом «data-», например:

          <a href="https://twitter.com/share" class="twitter-share-button" data-lang="ru">Твитнуть</a>
          

          уберем все лишнее, оставим только тег с атрибутом «data-» и оформим как положено оформлять html код, сделаем несколько вариантов с DOCTYPE для HTML 4.01, XHTML 1.0 и конечно HTML 5, который в DOCTYPE называется просто html. Проверим на валидность полученные коды. Причем не будем обращать внимание на прочие ошибки, нас интересует только атрибут «data-»:

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
          <html>
          	<head>
          		<title>HTML</title>
          	</head>
          	<body>
          		<a data-lang="ru">data-lang</a>
          	</body>
          </html>
          

          Line 7, Column 16: there is no attribute «DATA-LANG»
          <a data-lang="ru">data-lang</a>
          


          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
          <html>
          	<head>
          		<title>HTML</title>
          	</head>
          	<body>
          		<a data-lang="ru">data-lang</a>
          	</body>
          </html>
          

          Line 7, Column 16: there is no attribute «data-lang»
          <a data-lang="ru">data-lang</a>
          


          <!DOCTYPE html>
          <html>
          	<head>
          		<title>HTML</title>
          	</head>
          	<body>
          		<a data-lang="ru">data-lang</a>
          	</body>
          </html>
          

          This document was successfully checked as HTML5!

          Убедил, что атрибут «data-» разрешен только в HTML5?
        • 0
          Объясните пожалуйста, в чем суть именно такой конструкции?

          // Creating scripts on page
          x = d.getElementsByTagName(s)[0];
          x.parentNode.insertBefore(o,x);
          
          • 0
            К сожалению достоверно не знаю.
            Сам всегда использовал, что то типа:
            document.getElementsByTagName('head')[0].appendChild(script);
            

            или
            document.body.appendChild(script);
            


            Но коды полученные от twitter, Facebook и Google написаны имено так:
            // Creating scripts on page
            x = d.getElementsByTagName(s)[0];
            x.parentNode.insertBefore(o,x);
            


            Я подумал, что если я получил пример из трех солидных источников, значит именно такая конструкция является правильной в данном случае.

            Если кто то знает, почему twitter, Facebook и Google использовал именно эту конструкцию, расскажите, мне тоже интересно.
            • +1
              Потому что на странице может не быть ни head, ни body, и тогда скрипт упадёт. А хотя бы один тэг script на странице присутствует (вы же как-то вызываете этот код), значит и вставлять в DOM перед ним безопасно.
              Подход описан много где.
              • 0
                Ну в таком случаем можно и так написать:

                document.getElementsByTagName('script')[0].appendChild(script);
                


                Меня больше интересует почему:

                x.parentNode.insertBefore(o,x);
                
                • +1
                  Ну, аппендить в скрипт бесполезно. А вот у родителя лучше вызывать insertBefore, потому что, если родитель вдруг не до конца загружен, вызов appendChild у него приведёт к ошибке.
                  • 0
                    на странице может не быть ни head, ни body, и тогда скрипт упадёт.


                    Я тоже так подумал, но проведя несколько экспериментов немного засомневался. Дело в том, что если на странице код не оформлен, как положено, современные браузеры сами добавляют::
                    <html><head></head><body>
                    
                    </body></html>
                    


                    Конечно, возможно, что не все браузеры это делают, тем более старые или экзотические могут этого не делать. Так, что Выше объяснение, вероятнее всего верно.
            • 0
              Проблема не в том что у кого-то твиттер на работе заблокирован (трагично, да), а в том что лайки (и вообще такого рода тяжелые виджеты) будут тормозить при обычной загрузке, даже если весь сайт, кроме них, уже загружен.

              Решается все без такого рода костылей, весь блок выделяется в отдельный файл (статики или шаблона) и асинхронно подгружается простым гет-запросом после DOMready. Верстка, кстати при этом остается чистой, без ваших инлайн стилей.

              А вообще решения где есть просто ссылки на лайк (как на хабре, например), а не подгрузка джаваскрипта или (о боже) айфрейма, намного приятнее в плане загрузки, но «классические», много где, ими пока не заменить (отдельная тема). Сервисы вроде addthis работают по-первому принципу.

              Параграфы про использование хтмл5 и «старые» ссылки, вызвали реакцию вроде: «ну да, ну и че».
              • 0
                На самом деле конец статьи был немного другой.
                Я его убрал, т.к. получалось, что начал за здравие, а закончил за упокой. Поясню: действительно, Вы абсолютно, правы. «такого рода тяжелые виджеты) будут тормозить при обычной загрузке», по этому грузить их нужно только асинхронно + айфреймы, которые они используют мне тоже не нравятся. Но эти виджеты предлагает первоисточник, т.е. сами социальные сети. Я считаю, что мой код вполне приемлемый, рабочий вариант, хотя единственный плюс этих кнопок, что показаны счетчики.
              • 0
                Глубоко закопались вы. Есть сервисы, которые позволяют делать отличные социальные кнопочки в едином стиле за 5 минут, на выходе js скрипт. В итоге и код чистый, и кнопки в едином дизайне.
                • 0
                  Согласен с Вами, есть такие сервисы. А не подскажите, с счетчиками «лайков» есть? Я не нашел. И повторюсь: " цель статьи была рассказать об асинхронной загрузке javascript (это можно и в своих проектах использовать — грузить скрипты асинхронно) и кроссбраузерном указании атрибута data-, с помощью javascript"
                  • 0
                    Мне кажется и в выходной js скрипт таких сервисов его тоже можно было прикрутить и показать тоже самое. Было бы меньше вопрос к статье и реализации.
                  • 0
                    это разные кнопки
                    есть кнопки «поделиться» и их действительно можно загружать разными способами и сделать любыми по стилю, а есть кнопки like (нравится), а вот их «кастомизировать» нельзя.
                  • 0
                    Например, Twitter поменял уже ссылку, старая twitter.com/share, а новая twitter.com/intent/tweet
                    Почему же вы тогда в своём коде используете twitter.com/share?

                    Зато Google единственный кто использует асинхронную загрузку javascript, при помощи атрибута async
                    VK тоже может грузиться асинхронно.
                    • 0
                      Почему же вы тогда в своём коде используете twitter.com/share?

                      Это не я использую. Это программисты twitter как то странно себя ведут. Поменяли share ссылку и сами же дают старую!
                      Вот посмотрите: dev.twitter.com/docs/intents
                      Здесь описано как правильно шарить на twitter.
                      А если Вы решите зделать кнопку с помощью их же сервиса: twitter.com/about/resources/buttons
                      Получите ссылку:
                      <a href="https://twitter.com/share" class="twitter-share-button">Tweet</a>
                      

                      <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
                      


                      VK тоже может грузиться асинхронно
                      не спорю.
                      • –2
                        Может быть не в тему, но нет в русском языке приставки З-. Плакать хочется от таких комментариев.
                        • 0
                          Нет, серьезно? Вас не то что устраивает «ЗДЕЛАТЬ», так вы еще не довольны теми кто поправляет?
                          Вы живете в России, пишите на русском языке. Это общее развитие, это не какое-то специальное направление которое можно знать или нет. Я поправил не какой-то сложный речевой оборот, это то, чему даже детей в школе учат.
                          Куда мы катимся…
                    • 0
                      И insertBefore, и appendChild грузят скрипт асинхронно. Независимо от наличия атрибута async.
                      Синхронно скрипт будет загружен если он без атрибута async и вставляется через document.write. Ну или уже есть в HTML коде
                      • 0
                        Демка (смотрите логи): dl.dropbox.com/u/867515/scripts.html
                        • 0
                          Полезная информация.
                          Получается google «кодеры» перемудрили:

                            (function() {
                              var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
                              po.src = 'https://apis.google.com/js/plusone.js';
                              var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
                            })();
                          

                          со своим:

                          po.async = true;
                          

                          И я с ними.
                      • 0
                        Какой шаринг кнопок умеет показывать суммарное количество всех лайков (причем только успешных, а не нажатий), а также умеет лайкать без отображения отдельного окна, как эти нативные js лайки?
                        • 0
                          Сам бы хотел знать. Но похоже, на сегодняшний день, нет такого сервиса.
                        • 0
                          поставил. почему-то вконтакте два раза отображается на странице

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.