Jump to content
  • Плавающий боковой блок в Invision Community




    Любой плавающий блок в Invision Community 4 очень просто реализовать с помощью виджета ips.ui.sticky, который довольно просто в применении. Это может быть какой-то рекламный блок, двигающийся вместе с прокруткой страницы, или плавающий весь боковой блок. 

    Пример кода реализации с использованием IPS4 Javascript фреймворка:

    <div data-ipsSticky data-ipsSticky-relativeTo='#ipsLayout_sidebar' data-ipsSticky-disableIn='tablet,phone'>
      Плавающий блок
    </div>

     

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

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

    Безимени-1.gif

     

    Правильней было бы сначала просмотреть весь боковой блок, после чего закрепить его в нижней части окна браузера. Пример:

    Безимени-2.gif

    Для реализации такого вариант необходимо заменить шаблон core -> front -> global -> sidebar на следёющий код:

     

    Спойлер
    
    {{if (isset( \IPS\Output::i()->sidebar['enabled'] ) and \IPS\Output::i()->sidebar['enabled'] ) && ( ( isset( \IPS\Output::i()->sidebar['contextual'] ) && trim( \IPS\Output::i()->sidebar['contextual'] ) !== '' ) || ( isset( \IPS\Output::i()->sidebar['widgets']['sidebar'] ) && count( \IPS\Output::i()->sidebar['widgets']['sidebar'] ) ) || ( \IPS\Dispatcher::i()->application instanceof \IPS\Application AND \IPS\Dispatcher::i()->application->canManageWidgets() ) )}}
    	<div id='ipsLayout_sidebar' class='ipsLayout_sidebar{$position} {{if !( isset( \IPS\Output::i()->sidebar['contextual'] ) && trim( \IPS\Output::i()->sidebar['contextual'] ) !== '' ) && ( !isset( \IPS\Output::i()->sidebar['widgets']['sidebar'] ) || !count( \IPS\Output::i()->sidebar['widgets']['sidebar'] ) ) && \IPS\Dispatcher::i()->application->canManageWidgets()}}ipsLayout_sidebarUnused{{endif}}' data-controller='core.front.widgets.sidebar'>
    		<div class='ibtFloatSidebar'>
          	{{if isset( \IPS\Output::i()->sidebar['contextual'] ) && trim( \IPS\Output::i()->sidebar['contextual'] ) !== ''}}
    			<aside id="elContextualTools" class='ipsClearfix' {{if isset( \IPS\Output::i()->sidebar['sticky'] )}}data-ipsSticky{{endif}}>
    				{expression="\IPS\Output::i()->sidebar['contextual']" raw="true"}
    			</aside>
    		{{endif}}
    		{{if isset(\IPS\Output::i()->sidebar['widgets']['sidebar']) and count( \IPS\Output::i()->sidebar['widgets']['sidebar'] ) and ( \IPS\core\Advertisement::loadByLocation( 'ad_sidebar' ) ) }}
    			{advertisement="ad_sidebar"}
    			<br><br>
    		{{endif}}
    		{template="widgetContainer" group="global" app="core" params="'sidebar', 'vertical'"}
    	</div></div>
    {{endif}}
    
    <script>
     
      // обработчик "прилипания" контента в правой колонке
    (function(){
    	var a = document.querySelector('.ibtFloatSidebar'), b = null, K = null, Z = 0, P = 0, N = 0;  // если у P ноль заменить на число, то блок будет прилипать до того, как верхний край окна браузера дойдёт до верхнего края элемента, если у N — нижний край дойдёт до нижнего края элемента. Может быть отрицательным числом
    	window.addEventListener('scroll', Ascroll, false);
    	document.body.addEventListener('scroll', Ascroll, false);
    	function Ascroll() {
    		(function(jQuery) {
    			var c = document.querySelector('#ipsLayout_mainArea'),
    				Rc = c.getBoundingClientRect(),
    				Ra = a.getBoundingClientRect(),
    				R1bottom = Rc.bottom;
    			if (b == null) {
    				var Sa = getComputedStyle(a, ''), s = '';
    				for (var i = 0; i < Sa.length; i++) {
    					if (Sa[i].indexOf('overflow') == 0 || Sa[i].indexOf('padding') == 0 || Sa[i].indexOf('border') == 0 || Sa[i].indexOf('outline') == 0 || Sa[i].indexOf('box-shadow') == 0 || Sa[i].indexOf('background') == 0) {
    						s += Sa[i] + ': ' +Sa.getPropertyValue(Sa[i]) + '; '
    					}
    				}
    				b = document.createElement('div');
    				b.className = "stopSticky";
    				b.style.cssText = s + ' box-sizing: border-box; width: ' + a.offsetWidth + 'px;';
    				a.insertBefore(b, a.firstChild);
    				var l = a.childNodes.length;
    				for (var i = 1; i < l; i++) {
    					b.appendChild(a.childNodes[1]);
    				}
    			}
    			//просчитываем высоту колонки
    			a.style.height = b.getBoundingClientRect().height + 'px';
    			a.style.padding = '0';
    			a.style.border = '0';
    			var Rb = b.getBoundingClientRect(),
    				Rh = Ra.top + Rb.height,
    				W = document.documentElement.clientHeight,
    				R1 = Math.round(Rh - R1bottom),
    				R2 = Math.round(Rh - W);
    			if (Ra.bottom < R1bottom) {
    				if((Rc.height > Rb.height) /*&& (Rb.height > W)*/) { // проверка того, что высота колонки больше высоты контента
    					if (Rb.height > W) {
    						if (Ra.top < K) {  // скролл вниз
    							//console.log('скролл вниз');
    							if (R2 + N > R1) {  // не дойти до низа
    								//if ((Rb.bottom - W + N < 0) && (Rb.top - P < 0)) {  // подцепиться
    								if ((parseInt(Rb.bottom) - W + N) <= 0/* && (Rb.top + W < 0)*/) {  // подцепиться
    									b.className = 'startSticky';
    									b.style.top = W - Rb.height - N + 'px';
    									Z = N + Ra.top + Rb.height - W;
    								} else {
    									b.className = 'stopSticky';
    									b.style.top = -Z + 'px';
    								}
    							} else {
    								b.className = 'stopSticky';
    								b.style.top = -R1 + 'px';
    								Z = R1;
    							}
    						} else {  // скролл вверх
    							//console.log('скролл вверх');
    							if (Ra.top - P < 0) {  // не дойти до верха
    								if (Rb.top - P >= 0) {  // подцепиться
    									b.className = 'startSticky';
    									b.style.top = P + 'px';
    									Z = Ra.top - P;
    								} else {
    									b.className = 'stopSticky';
    									b.style.top = -Z + 'px';
    								}
    							} else {
    								b.className = '';
    								b.style.top = '';
    								Z = 0;
    							}
    						}
    						K = Ra.top;
    					} else {
    						if ((Ra.top - P) <= 0) {
    							if ((Ra.top - P) <= R1) {
    								b.className = 'stopSticky';
    								b.style.top = -R1 + 'px';
    							} else {
    								b.className = 'startSticky';
    								b.style.top = P + 'px';
    							}
    						} else {
    							b.className = '';
    							b.style.top = '';
    						}
    					}
    				} else {
    					// если высота контента меньше высоты колонки, то "прибиваем" колонку к верху
    					Z = 0;
    					b.className = 'stopSticky';
    					b.style.top = Z + 'px';
    				}
    				window.addEventListener('resize', function() {
    					a.children[0].style.width = getComputedStyle(a, '').width
    				}, false);
    			}
    		})(jQuery)
    	}
    
    })()
    </script>

     

    В custom.css добавим:

    Спойлер
    
    /**
     * This file is for your custom CSS.
     * This file is not modified or overwritten during upgrades
     * InvisionByte.ru
     */
    #ipsLayout_mainArea {height: auto;}
    .startSticky {position: fixed; z-index: 101;}
    .stopSticky {position: relative; z-index: 101;}

     



    • Like 3


      Report запись


    User Feedback


    There are no comments to display.



    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.
    Note: Your post will require moderator approval before it will be visible.

    Guest
    Add a comment...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    Loading...

Messenger

    ×
    ×
    • Create New...

    Important Information

    By using our site you agree to our Privacy Policy