Адаптивный виджет для сообществ вконтакте

Сложность

HTML 15%
JavaScript 65%

Описание

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

Пришло время сделать адаптивным данный плагин, и сделаем это все на нативном JavaScript.

HTML часть

Подключим api вконтакте к нашей странице через скрипт.

Зададим div с id=vk_widget, данный блок будет выполнять у нас функцию обертки; в последующем, при помощи JavaScript, в него мы будем помещать сам виджет.

<script type="text/javascript" src="//vk.com/js/api/openapi.js?146"></script>
<div id="vk_widget"></div>

CSS часть

Специальных стилей здесь ненужно, но вы конечно можете задавать нужные стили окружению(например отступы для обертки).

// Нет специальных стилей.

JavaScript часть

Создадим функцию vkWidgetInit, она будет служить для запуска нашего виджета.

Создадим переменную containerWidth, мы запишем туда ширину контейнера(id="vk_widget").

Далее методом innerHTML помещаем в наш контейнер сам виджет, и зададим ему  id="vk_groups".

В VK.Widgets.Group прописываем все нужные настройки(с ними можно ознакомиться на оф. сайте виджета). В настройки записываем наш id(vk_groups), а в ширину записываем ширину нашего контейнера(переменная containerWidth).

Подключаем обработчик(DOMContentLoaded) к нашему документу(странице), и когда браузер полностью загрузит HTML и построит DOM-дерево, у нас идет вызов нашей функции(vkWidgetInit();).

И в конце мы подключаем обработчик на ресайз окна, и при изменении размера окна браузера мы будем вновь запускать наш плагин, предварительно удалив у него атрибут src. Особенностью здесь является то, что мы используем вспомогательную функцию resizeThrottler, зачем она нужна, можно узнать здесь  developer.mozilla.org

function vkWidgetInit() {
  var containerWidth = document.querySelector('#vk_widget').clientWidth;

  document.querySelector('#vk_widget').innerHTML = '<div id="vk_groups"></div>';

  VK.Widgets.Group("vk_groups", {
    mode: 4,
    no_cover: 1,
    color3: '507299',
    width: containerWidth,
  }, 20003922);
}

/* begin Document Ready */
document.addEventListener('DOMContentLoaded', function() {

  vkWidgetInit();

  /* begin Window Resize */
  (function() {
    window.addEventListener("resize", resizeThrottler, false);

    var resizeTimeout;

    function resizeThrottler() {
      if (!resizeTimeout) {
        resizeTimeout = setTimeout(function() {
          resizeTimeout = null;
          actualResizeHandler();
        }, 66);
      }
    }

    function actualResizeHandler() {
      vkWidgetInit();
    }

  })();
  /* end Window Resize */

});
/* end Document Ready */

Демонстрация

Мультивиджет

«Может Вы подскажете, как объединить два таких скрипта в один? Чтобы один скрипт на два виджета был)»

Вопрос из комментария.

HTML

<script type="text/javascript" src="//vk.com/js/api/openapi.js?146"></script>
<div id="vk_widget-news" class="vk_widget"></div>
<div id="vk_widget-group" class="vk_widget"></div>

JavaScript

'use strict';

var vkWidgetList = document.querySelectorAll('.vk_widget');
var vkCounter = vkWidgetList.length + 1;

function vkWidgetNewsInit(vkWidgetContainer, containerWidth) {
	var container = vkWidgetContainer;
	var vk_groups = document.createElement('div');
	vk_groups.setAttribute('id', 'vk_groups' + (vkCounter = vkCounter - 1));

	container.innerHTML = '';
	container.appendChild(vk_groups);

	VK.Widgets.Group(
		vk_groups.getAttribute('id'), {
			mode: 4,
			no_cover: 1,
			color3: 'D42B36',
			width: containerWidth
		},
		20003922
	);
}

function vkWidgetGroupInit(vkWidgetContainer, containerWidth) {
	var container = vkWidgetContainer;
	var vk_groups = document.createElement('div');
	vk_groups.setAttribute('id', 'vk_groups' + (vkCounter = vkCounter - 1));

	container.innerHTML = '';
	container.appendChild(vk_groups);

	VK.Widgets.Group(
		vk_groups.getAttribute('id'), {
			mode: 3,
			no_cover: 1,
			color3: '507299',
			width: containerWidth
		},
		20003922
	);
}

function vkWidgetInit(vkWidgetContainer) {
	var containerWidth = vkWidgetContainer.clientWidth;
	var containerId = vkWidgetContainer.getAttribute('id');

	switch (containerId) {
		case 'vk_widget-news':
			vkWidgetGroupInit(vkWidgetContainer, containerWidth);
			break;
		case 'vk_widget-group':
			vkWidgetNewsInit(vkWidgetContainer, containerWidth);
			break;
	}
}

/* begin Document Ready */
document.addEventListener("DOMContentLoaded", function() {
	for (var i = 0, length1 = vkWidgetList.length; i < length1; i++) {
		vkWidgetInit(vkWidgetList[i]);
	}

	/* begin Window Resize */
	(function() {
		window.addEventListener("resize", resizeThrottler, false);

		var resizeTimeout;

		function resizeThrottler() {
			if (!resizeTimeout) {
				resizeTimeout = setTimeout(function() {
					resizeTimeout = null;
					actualResizeHandler();
				}, 66);
			}
		}

		function actualResizeHandler() {
			for (var i = 0, length1 = vkWidgetList.length; i < length1; i++) {
				vkWidgetInit(vkWidgetList[i]);
			}
		}
	})();
	/* end Window Resize */
});
/* end Document Ready */

Был найден баг в данном коде(где сразу несколько виджетов). Если мы включаем wide=1/расширенный режим(см. документацию к виджету на оф. сайте), тогда появляется баг, что порой блок с данным режимом выезжает за контейнер родителя. Полагаю, это проблема виджета, а не моего решения, т.к. если не включать wide=1, тогда все работает стабильно.

Демонстрация