Страницы

Поиск по вопросам

четверг, 4 октября 2018 г.

Неизвестная ошибка при создании собственной функции

Писал свою функцию для присвоения свойств к псевдоэлементам и заметил неведомую ошибку. Присваивание свойств идёт через добавления строк в styleSheet.
Когда в третьем случае вызываю функцию, почему то красится в синий первый элемент, хотя color для него я не ставил.
(function() { var setPseudoElement = function(parameters) { for (var element of parameters.elements.get()) { if (!element.pseudoElements) element.pseudoElements = { styleSheet: null, before: { index: null, properties: null }, after: { index: null, properties: null } }; var selector = (function() { if (element.id) { return '#' + element.id + '::' + parameters.pseudoElement; } else { var parentsList = $(element).parents().map(function() { return this.tagName.toLowerCase(); }).get().reverse().join(' > ') + ' > ' + element.tagName.toLowerCase(); var elementClass = element.classList.length ? '.' + $(element.classList).get().join('.') : ''; var elementAttributes = element.hasAttributes() ? $(element.attributes).get().map(function(className) { return className.nodeName !== 'class' ? className.nodeValue ? '[' + className.nodeName + '="' + className.nodeValue + '"]' : '[' + className.nodeName + '"]' : ''; }).join('') : ''; var elementNthChild = ':nth-child(' + ($(element).index() + 1) + ')'; return parentsList + elementClass + elementAttributes + elementNthChild + '::' + parameters.pseudoElement; }; })(); if (!element.pseudoElements.styleSheet) { if (document.styleSheets[0]) { element.pseudoElements.styleSheet = document.styleSheets[0]; } else { var styleSheet = document.createElement('style'); document.head.appendChild(styleSheet); element.pseudoElements.styleSheet = styleSheet.sheet; }; }; if (element.pseudoElements[parameters.pseudoElement].properties !== null && element.pseudoElements[parameters.pseudoElement].index !== null) { element.pseudoElements.styleSheet.deleteRule(element.pseudoElements[parameters.pseudoElement].index); }; if (typeof parameters.argument === 'object') { if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) { var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length; element.pseudoElements[parameters.pseudoElement].index = newIndex; element.pseudoElements[parameters.pseudoElement].properties = parameters.argument; }; var properties = ''; for (var property in parameters.argument) { element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]; }; for (var property in element.pseudoElements[parameters.pseudoElement].properties) { properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; '; }; element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index); } else if (parameters.argument !== undefined && parameters.property !== undefined) { } else if (parameters.argument !== undefined && parameters.property === undefined) { } else { console.error('Invalid values!'); return false; }; }; }; $.fn.cssBefore = function(argument, property) { setPseudoElement({ elements: this, pseudoElement: 'before', argument: argument, property: property }); }; })(); $(function() { // Случай 1 $('.el0').cssBefore({ 'content': '"Новый \'before\'"', 'color': 'green' }); // Случай 2 $('.el1').cssBefore({ 'content': '"Новый \'before\' №2"', 'color': 'blue' }); // Случай 3 $('.el0').cssBefore({ 'content': '"Новый \'before\' №3"' }); }); .element { width: 480px; margin: 0 auto; border: 2px solid red; } .element:before { content: "Старый 'before'"; color: orange; }


Почему в третьем случае красится в синий первый элемент? Как это исправить?

UPDATA:
Если выводить в консоль значения элементов после каждого присваивания, то выходят очень странные значения:
(function () { var i = 1; var setPseudoElement = function (parameters) { for (var element of parameters.elements.get()) { if (!element.pseudoElements) element.pseudoElements = {styleSheet: null, before: {index: null, properties: null}, after: {index: null, properties: null}}; var selector = (function () { if (element.id) { return '#' + element.id + '::' + parameters.pseudoElement; } else { var parentsList = $(element).parents().map(function () { return this.tagName.toLowerCase(); }).get().reverse().join(' > ') + ' > ' + element.tagName.toLowerCase(); var elementClass = element.classList.length ? '.' + $(element.classList).get().join('.') : ''; var elementAttributes = element.hasAttributes() ? $(element.attributes).get().map(function (className) { return className.nodeName !== 'class' ? className.nodeValue ? '[' + className.nodeName + '="' + className.nodeValue + '"]' : '[' + className.nodeName + '"]' : ''; }).join('') : ''; var elementNthChild = ':nth-child(' + ($(element).index() + 1) + ')'; return parentsList + elementClass + elementAttributes + elementNthChild + '::' + parameters.pseudoElement; }; })(); if (!element.pseudoElements.styleSheet) { if (document.styleSheets[0]) { element.pseudoElements.styleSheet = document.styleSheets[0]; } else { var styleSheet = document.createElement('style'); document.head.appendChild(styleSheet); element.pseudoElements.styleSheet = styleSheet.sheet; }; }; if (element.pseudoElements[parameters.pseudoElement].properties !== null && element.pseudoElements[parameters.pseudoElement].index !== null) { element.pseudoElements.styleSheet.deleteRule(element.pseudoElements[parameters.pseudoElement].index); }; if (typeof parameters.argument === 'object') { if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) { var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length; element.pseudoElements[parameters.pseudoElement].index = newIndex; element.pseudoElements[parameters.pseudoElement].properties = parameters.argument; }; var properties = ''; for (var property in parameters.argument) { element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]; }; for (var property in element.pseudoElements[parameters.pseudoElement].properties) { properties += property + ': ' + element.pseudoElements[parameters.pseudoElement].properties[property] + ' !important; '; }; element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index); console.log('Номер запуска: ' + Math.round(i / 2) + '; Номер присваивания элементу: ' + i); console.log({ 'Элемент 1': $('.el0:not(.el1)').get(0).pseudoElements, 'Элемент 2': $('.el0.el1').get(0).pseudoElements, 'Элемент 3': $('.el1:not(.el0)').get(0).pseudoElements }); i++; } else if (parameters.argument !== undefined && parameters.property !== undefined) { } else if (parameters.argument !== undefined && parameters.property === undefined) { } else { console.error('Invalid values!'); return false; }; }; }; $.fn.cssBefore = function (argument, property) { setPseudoElement ({ elements: this, pseudoElement: 'before', argument: argument, property: property }); }; })(); $(function() { // Случай 1 $('.el0').cssBefore({ 'content': '"Новый \'before\'"', 'color': 'green' }); // Случай 2 $('.el1').cssBefore({ 'content': '"Новый \'before\' №2"', 'color': 'blue' }); // Случай 3 $('.el0').cssBefore({ 'content': '"Новый \'before\' №3"' }); }); .element { width: 480px; margin: 0 auto; border: 2px solid red; } .element:before { content: "Старый 'before'"; color: orange; }

Если смотреть в консоль, то уже при первом вызове функции, элемент №1 имеет синий цвет и содержимое №3


Ответ

Думаю что я нашел проблему:
element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
где parameters.argument — это объект. Когда мы делаем первый проход, мы задаем его для первого и второго элемента. Когда на втором проходе мы меняем его для второго случая, он меняется и для первого тоже.
И вот пруф и решение
element.pseudoElements[parameters.pseudoElement].properties = Object.assign({}, parameters.argument);

Комментариев нет:

Отправить комментарий