© 2008-2024 г.
Все права защищены

Создание дополнительных breakpoints в Oxygen Builder

Если вы используете плагин Oxygen Builder в качестве создания сайтов на Wordpress, то вы могли заметить проблему данного плагина ,а именно точек остановки для создания responsive дизайна всего 3. Это крайне мало и вызывает недоумение, чтобы такой мощный конструктор страниц предлагал такое ограниченное количество breakpoints. 

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

Когда увидел в коде след индусских разработчиков

Содержание статьи

Требования

  1. Wordpress 6
  2. PHP 7.4
  3. Oxygen builder 4.9

Файлы, которые подверглись изменению

  1. oxygen/component-framework/component-init.php
  2. oxygen/component-framework/toolbar/views/global-settings/page-width.view.php
  3. oxygen/component-framework/angular/controllers/controller.media-queries.js
  4. oxygen/component-framework/angular/controllers/controller.options.js
  5. oxygen/component-framework/angular/controllers/iframe.min.js

Теперь подробно разберем какие правки я внес по каждому файлу.

PHP-обработка breakpoints в Oxygen builder

Файл component-init.php

Практически в самом начале я вижу создание переменных под разные точки остановки media query

$media_tablet_width = oxygen_vsb_get_breakpoint_width('tablet');
$media_phone_landscape_width = oxygen_vsb_get_breakpoint_width('phone-landscape');
$media_phone_portrait_width = oxygen_vsb_get_breakpoint_width('phone-portrait');

Добавляем свои переменные. Всего я добавил 4 дополнительных точки:

  1. small-desktop
  2. ipad-portrait
  3. phone-xl
  4. phone-xs
$media_small_desktop_width = oxygen_vsb_get_breakpoint_width('small-desktop');
$media_ipad_portrait_width = oxygen_vsb_get_breakpoint_width('ipad-portrait');
$media_tablet_width = oxygen_vsb_get_breakpoint_width('tablet');
$media_phone_landscape_width = oxygen_vsb_get_breakpoint_width('phone-landscape');
$media_phone_portrait_width = oxygen_vsb_get_breakpoint_width('phone-portrait');
$media_phone_xl_width = oxygen_vsb_get_breakpoint_width('phone-xl');
$media_phone_xs_width = oxygen_vsb_get_breakpoint_width('phone-xs');

Ниже в массивы добавим свои точки остановки.

Готовый код:

global $media_queries_list;
$media_queries_list = array (
	"default" 	=> array(
		"maxSize" 	=> "100%",
		"title" 	=> "Full Screen"
	),

	"page-width" 	=> array(
		"maxSize" 	=> "", // set when actually use
		"title" 	=> "Page container and below"
	),
	"small-desktop" => array(
		"maxSize" 	=> ($media_small_desktop_width) . 'px',
		"title" 	=> "Less than {$media_small_desktop_width}px"
	),
	"ipad-portrait" => array(
		"maxSize" 	=> ($media_ipad_portrait_width) . 'px',
		"title" 	=> "Less than {$media_ipad_portrait_width}px"
	),
	"tablet" => array(
		"maxSize" 	=> ($media_tablet_width - 1) . 'px',
		"title" 	=> "Less than {$media_tablet_width}px"
	),
	"phone-landscape" => array(
		"maxSize" 	=> ($media_phone_landscape_width - 1) . 'px',
		"title" 	=> "Less than {$media_phone_landscape_width}px"
	),
	"phone-portrait" => array(
		"maxSize" 	=> ($media_phone_portrait_width - 1) . 'px',
		"title" 	=> "Less than {$media_phone_portrait_width}px"
	),
    "phone-xl" => array(
        "maxSize" 	=> ($media_phone_xl_width - 1) . 'px',
        "title" 	=> "Less than {$media_phone_xl_width}px"
    ),
    "phone-xs" => array(
        "maxSize" 	=> ($media_phone_xs_width - 1) . 'px',
        "title" 	=> "Less than {$media_phone_xs_width}px"
    ),
);

global $media_queries_list_above;
$media_queries_list_above = array (
	"default" => array(
		"minSize" 	=> "100%",
		"title" 	=> "Full Screen"
	),

	"page-width" => array(
		"minSize" 	=> "", // set when actually use
		"title" 	=> "Above page container"
	),
	"small-desktop" => array(
		"minSize" 	=> $media_small_desktop_width . 'px',
		"title" 	=> "At or above {$media_small_desktop_width}px"
	),
	"ipad-portrait" => array(
		"minSize" 	=> $media_ipad_portrait_width . 'px',
		"title" 	=> "At or above {$media_ipad_portrait_width}px"
	),
	"tablet" => array(
		"minSize" 	=> $media_tablet_width . 'px',
		"title" 	=> "At or above {$media_tablet_width}px"
	),
	"phone-landscape" => array(
		"minSize" 	=> $media_phone_landscape_width . 'px',
		"title" 	=> "At or above {$media_phone_landscape_width}px"
	),
	"phone-portrait" => array(
		"minSize" 	=> $media_phone_portrait_width . 'px',
		"title" 	=> "At or above {$media_phone_portrait_width}px"
	),
    "phone-xl" => array(
        "minSize" 	=> $media_phone_xs_width . 'px',
        "title" 	=> "At or above {$media_phone_xl_width}px"
    ),
    "phone-xs" => array(
        "minSize" 	=> $media_phone_xs_width . 'px',
        "title" 	=> "At or above {$media_phone_xs_width}px"
    ),
);

Далее внизу на строке 4915 пропишем значения по умолчанию:

"breakpoints" => array(
					'small-desktop' => 1285,
					'ipad-portrait' => 1026,
					'tablet' => 992,
					'phone-landscape' => 768,
					'phone-portrait' => 480,
                    'phone-xl' => 435,
                    'phone-xs' => 380,
				),

Файл page-width.view.php

Здесь происходит вывод полей в настройки конструктора Oxygen builder. Добавляем также свои breakpoints

<?php
$ct_breakpoints = array(
	'small-desktop' => __("Small desktop", 'oxygen'),
	'ipad-portrait' => __("Ipad", 'oxygen'),
	'tablet' => __("Tablet", 'oxygen'),
	'phone-landscape' => __("Landscape", 'oxygen'),
	'phone-portrait' => __("Portrait", 'oxygen'),
    'phone-xl' => __("Phone Xl", 'oxygen'),
    'phone-xs' => __("Phone Xs", 'oxygen'),
);
foreach ($ct_breakpoints as $bp_name => $bp_label){
?>

JS обработка breakpoints

Файл controller.media-queries.js

Здесь в самом начале в функцию initMedia добавим свои переменные:

$scope.initMedia = function() {
		var pageWidth = $scope.getPageWidth();
		var smallDesktopWidth = $scope.getBreakPointWidth('small-desktop');
		var ipadPortraitWidth = $scope.getBreakPointWidth('ipad-portrait');
		var tabletWidth = $scope.getBreakPointWidth('tablet');
		var phoneLandscapeWidth = $scope.getBreakPointWidth('phone-landscape');
		var phonePortraitWidth = $scope.getBreakPointWidth('phone-portrait');
		var phoneXlWidth = $scope.getBreakPointWidth('phone-xl');
		var phoneXsWidth = $scope.getBreakPointWidth('phone-xs');
		
        $scope.previousBreakPointsValues = {
            'page-width': {
                'page': $scope.pageSettingsMeta['max-width'],
                'global': $scope.globalSettings['max-width'],
            },



			'small-desktop': $scope.globalSettings.breakpoints['small-desktop'],
			'ipad-portrait': $scope.globalSettings.breakpoints['ipad-portrait'],
            'tablet': $scope.globalSettings.breakpoints['tablet'],
            'phone-landscape': $scope.globalSettings.breakpoints['phone-landscape'],
            'phone-portrait': $scope.globalSettings.breakpoints['phone-portrait'],
			'phone-xl': $scope.globalSettings.breakpoints['phone-xl'],
			'phone-xs': $scope.globalSettings.breakpoints['phone-xs'],
        };

		$scope.mediaList = {
            default: {
                maxSize: "100%",
                title: "Full Screen"
            },
            "page-width": {
                maxSize: pageWidth + "px",
                title: "Page container (" + pageWidth + "px) and below"
            },
			"small-desktop": {
                maxSize: (smallDesktopWidth - 1) + "px",
                title: "Less than " + smallDesktopWidth + "px"
            },
			"ipad-portrait": {
                maxSize: (ipadPortraitWidth) + "px",
                title: "Less than " + ipadPortraitWidth + "px"
            },
            "tablet": {
                maxSize: (tabletWidth - 1) + "px",
                title: "Less than " + tabletWidth + "px"
            },
            "phone-landscape": {
                maxSize: (phoneLandscapeWidth - 1) + "px",
                title: "Less than " + phoneLandscapeWidth + "px"
            },
            "phone-portrait": {
                maxSize: (phonePortraitWidth - 1) + "px",
                title: "Less than " + phonePortraitWidth + "px"
            },
			"phone-xl": {
				maxSize: (phoneXlWidth - 1) + "px",
				title: "Less than " + phoneXlWidth + "px"
			},
			"phone-xs": {
				maxSize: (phoneXsWidth - 1) + "px",
				title: "Less than " + phoneXsWidth + "px"
			}
        };

		$scope.mediaListAbove = {
            default: {
                minSize: "100%",
                title: "Full Screen"
            },
            "page-width": {
                minSize: (pageWidth + 1) + "px",
                title: "Above Page container (" + pageWidth + "px)"
			},
			"small-desktop": {
                minSize: smallDesktopWidth + "px",
                title: "At or above " + smallDesktopWidth + "px"
            },
			"ipad-portrait": {
                minSize: ipadPortraitWidth + "px",
                title: "At or above " + ipadPortraitWidth + "px"
            },
            "tablet": {
                minSize: tabletWidth + "px",
                title: "At or above " + tabletWidth + "px"
            },
            "phone-landscape": {
                minSize: phoneLandscapeWidth + "px",
                title: "At or above " + phoneLandscapeWidth + "px"
            },
            "phone-portrait": {
                minSize: phonePortraitWidth + "px",
                title: "At or above " + phonePortraitWidth + "px"
            },
			"phone-xl": {
				minSize: phoneXlWidth + "px",
				title: "At or above " + phoneXlWidth + "px"
			},
			"phone-xs": {
				minSize: phoneXsWidth + "px",
				title: "At or above " + phoneXsWidth + "px"
			}
        };
	}

Файл controller.options.js

Здесь в функцию breakPointsUpdate в оператор switch добавим:

 switch(id) {
            case 'small-desktop':
                minWidth = $scope.getBreakPointWidth('small-desktop')+1;
                maxWidth = $scope.getBreakPointWidth('small-desktop');
                name = 'Small desktop';
                break;
            case 'ipad-portrait':
                minWidth = $scope.getBreakPointWidth('ipad-portrait')+1;
                maxWidth = $scope.getBreakPointWidth('ipad-portrait');
                name = 'Ipad portrait';
                break;
            case 'tablet':
                minWidth = $scope.getBreakPointWidth('phone-landscape')+1;
                maxWidth = $scope.getPageWidth()-1;
                name = 'Tablet';
                break;

            case 'phone-landscape':
                minWidth = $scope.getBreakPointWidth('phone-portrait')+1;
                maxWidth = $scope.getBreakPointWidth('tablet')-1;
                name = 'Landscape';
                break;
                
            case 'phone-portrait':
                minWidth = 320;
                maxWidth = $scope.getBreakPointWidth('phone-landscape')-1;
                name = 'Portrait';
                break;
            case 'phone-xl':
                minWidth = $scope.getBreakPointWidth('phone-xl')+1;
                maxWidth = $scope.getBreakPointWidth('phone-xl')-1;
                name = 'Phone Xl';
                break;
            case 'phone-xs':
                minWidth = $scope.getBreakPointWidth('phone-xs')+1;
                maxWidth = $scope.getBreakPointWidth('phone-xs')-1;
                name = 'Phone Xs';
                break;
            default:
                validate = false;
        }

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

if( width < minWidth ){
  error = "<div>" + name + " value must be greater than or equal to " + minWidth + "</div>";
  } else
  if( width > maxWidth ) {
     error = "<div>" + name + " value must be less than or equal to " + maxWidth + "</div>";
}

Получаем такой код:

  if( validate ){
            /*if( width < minWidth ){
                error = "<div>" + name + " value must be greater than or equal to " + minWidth + "</div>";
            } else
            if( width > maxWidth ) {
                error = "<div>" + name + " value must be less than or equal to " + maxWidth + "</div>";
            }*/
            
            if( error ){
                // Revert to previous breakpoint width if the entered value is invalid
                $scope.globalSettings.breakpoints[id] = $scope.previousBreakPointsValues[id];
                $scope.showNoticeModal(error);
                return;
            }
            
            // Store the new value as new valid breakpoint value
            $scope.previousBreakPointsValues[id] = $scope.globalSettings.breakpoints[id];
        }

Файл iframe.min.js

Теперь переходим к самой главной боли данного плагина. Данный файл представляет собой минифицированный webpack, который очень сложно было разбирать и находить, что где работает.

В контроллер ControllerMediaQueries добавляем свои переменные новых breakpoints:

var e = c.getPageWidth();
        var sd = c.getBreakPointWidth("small-desktop");
        var ip = c.getBreakPointWidth("ipad-portrait");
        var t = c.getBreakPointWidth("tablet");
        var i = c.getBreakPointWidth("phone-landscape");
        var s = c.getBreakPointWidth("phone-portrait");
        var xl = c.getBreakPointWidth("phone-xl");
        var xs = c.getBreakPointWidth("phone-xs");
     

        c.previousBreakPointsValues = {
            "page-width": {
                page: c.pageSettingsMeta["max-width"],
                global: c.globalSettings["max-width"]
            },
            "small-desktop": c.globalSettings.breakpoints["small-desktop"],
            "ipad-portrait": c.globalSettings.breakpoints["ipad-portrait"],
            tablet: c.globalSettings.breakpoints.tablet,
            "phone-landscape": c.globalSettings.breakpoints["phone-landscape"],
            "phone-portrait": c.globalSettings.breakpoints["phone-portrait"],
            "phone-xl": c.globalSettings.breakpoints["phone-xl"],
            "phone-xs": c.globalSettings.breakpoints["phone-xs"]
            
        };

        c.mediaList = {
            default: {
                maxSize: "100%",
                title: "Full Screen"
            },
            "page-width": {
                maxSize: e + "px",
                title: "Page container (" + e + "px) and below"
            },
            "small-desktop": {
                maxSize: sd + 1 + "px",
                title: "Less than " + sd + "px"
            },
            "ipad-portrait": {
                maxSize: ip + 1 + "px",
                title: "Less than " + ip + "px"
            },
            tablet: {
                maxSize: t - 1 + "px",
                title: "Less than " + t + "px"
            },
            "phone-landscape": {
                maxSize: i - 1 + "px",
                title: "Less than " + i + "px"
            },
            "phone-portrait": {
                maxSize: s - 1 + "px",
                title: "Less than " + s + "px"
            },
            "phone-xl": {
                maxSize: xl + 1 + "px",
                title: "Less than " + xl + "px"
            },
            "phone-xs": {
                maxSize: xs + 1 + "px",
                title: "Less than " + xs + "px"
            }
           
        };

        c.mediaListAbove = {
            default: {
                minSize: "100%",
                title: "Full Screen"
            },
            "page-width": {
                minSize: e + 1 + "px",
                title: "Above Page container (" + e + "px)"
            },
            "small-desktop": {
                minSize: sd + "px",
                title: "At or above " + sd + "px"
            },
            "ipad-portrait": {
                minSize: ip + "px",
                title: "At or above " + ip + "px"
            },
            tablet: {
                minSize: t + "px",
                title: "At or above " + t + "px"
            },
            "phone-landscape": {
                minSize: i + "px",
                title: "At or above " + i + "px"
            },
            "phone-portrait": {
                minSize: s + "px",
                title: "At or above " + s + "px"
            },
            "phone-xl": {
                minSize: xl + "px",
                title: "At or above " + xl + "px"
            },
            "phone-xs": {
                minSize: xs + "px",
                title: "At or above " + xs + "px"
            },
           
        };
    };

Примерно на строке 10709 вносим изменения в код и обязательно комментируем проверку в if (s) :

b.breakPointsUpdate = function (e) {
        var o;
        var t;
        var n;
        var i = b.getBreakPointWidth(e);
        var s = true;
        var a = false;
        switch (e) {
            case "tablet":
                o = b.getBreakPointWidth("phone-landscape") + 1;
                t = b.getPageWidth() - 1;
                n = "Tablet";
                break;
            case "phone-landscape":
                o = b.getBreakPointWidth("phone-portrait") + 1;
                t = b.getBreakPointWidth("tablet") - 1;
                n = "Landscape";
                break;
            case "phone-portrait":
                o = 320;
                t = b.getBreakPointWidth("phone-landscape") - 1;
                n = "Portrait";
                break;
                case "small-desktop":
                o = b.getBreakPointWidth("small-desktop") + 1;
                t = b.getBreakPointWidth("small-desktop") + 1;
                n = "Small Desktop";
                break;
            case "ipad-portrait":
                o = b.getBreakPointWidth("ipad-portrait") + 1;
                t = b.getPageWidth() - 1;
                n = "iPad Portrait";
                break;
            case "phone-xl":
                o = b.getBreakPointWidth("phone-xl") + 1;
                t = b.getPageWidth() - 1;
                n = "Phone Xl";
                break;
            case "phone-xs":
                o = b.getBreakPointWidth("phone-xs") + 1;
                t = b.getPageWidth() - 1;
                n = "Phone Xs";
                break;
            default:
                s = false;
        }
        if (s) {
           /* if (i < o) {
                a = "<div>" + n + " value must be greater than or equal to " + o + "</div>";
            } else if (t < i) {
                a = "<div>" + n + " value must be less than or equal to " + t + "</div>";
            }*/
            if (a) {
                b.globalSettings.breakpoints[e] = b.previousBreakPointsValues[e];
                b.showNoticeModal(a);
                return;
            }
            b.previousBreakPointsValues[e] = b.globalSettings.breakpoints[e];
        }
        b.mediaList[e] = {
            maxSize: i + "px",
            title: "Less than " + i + "px"
        };
        b.mediaListAbove[e] = {
            minSize: i + "px",
            title: "At or above " + i + "px"
        };
        b.updateAllComponentsCacheStyles();
        b.outputCSSOptions();
        b.outputPageSettingsCSS();
        y.adjustViewportContainer();
        b.unsavedChanges();
    };

Иконки, которые изменяют breakpoints в конструкторе

В директории oxygen/component-framework/toolbar/UI/oxygen-icons/media-query есть названия иконок и необходимо либо подгрузить свои иконки, либо скопировать и вставить уже текущие только с новыми названиями. Я сделал по второму варианту и как вы видите названия иконок соответствуют названию breakpoints. Если этого не сделать, то иконки не появятся в конструкторе.

Настройки breakpoints в конструкторе

Важный момент без которого у вас не заработают свои точки остановки и вы не будете видеть изменения в редакторе. В файле component-init.php мы указывали значения своих точек остановок по умолчанию и чтобы выставить корректно настройку нужно прибавить 5 пикселей. Если в значении по умолчанию у вас было 480px, то в настройках выставляете 485px или выше. По сути точные значения не нужны при мобильной верстке, но корректно редактор будет работать именно при таких значений (+5px). 

Проверка точек остановок

Как видите все точки появились и вам обязательно нужно будет очистить кеш в настройках конструктора.

Плюсы моего решения

  1. В самом редакторе разработчиками было сделано так, что точки остановки показывали страницу не совсем корректно, а именно если у вас точка остановки была 768px а другая за ним 480px, то страница показывала 481px вместо 768px, что затрудняло верстку сайта. Теперь значение приближено к тому размеру, какое было указано вами.
  2. Теперь можно полностью создать страницу без использования своего кода при мобильной верстке.

Минусы решения

Нельзя обновлять плагин

Файлы для скачивания

Я подготовил файлы сразу для замены в плагине. Просто распакуйте и перенесите в папку plugins соглашаясь с заменами.

Обратите внимание, что я не несу ответственность, если у вас пойдет что-то не так и не занимаюсь бесплатной технической поддержкой плагина!

Заключение

Сегодня мы решили вопрос с дополнительными breakpoints в плагине Oxygen builder и это не может не радовать!

Привет Username! Я Алексей Костюк
14 лет занимаюсь тем, что помогаю людям создавать сайты и дизайн, настраивать рекламу, продвигать проекты в Интернете. Ну и иногда еще принтер починить ;) Я создал этот блог, чтобы делить своим опытом и мыслями, а если вам нужна моя помощь, то вы знаете, где меня искать. Перейти на мой сайт