1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
<!DOCTYPE html>
<title>CSSOM test: declaration block after setting via CSSOM</title>
<link rel="help" href="https://drafts.csswg.org/cssom/#set-a-css-declaration-value">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
function generateCSSDeclBlock(props) {
let elem = document.createElement("div");
let cssText = props.map(({name, value, priority}) => {
let longhand = `${name}: ${value}`;
if (priority) {
longhand += "!" + priority;
}
return longhand + ";";
}).join(" ");
elem.setAttribute("style", cssText);
return elem.style;
}
function compareByName(a, b) {
if (a.name < b.name) return -1;
if (a.name > b.name) return 1;
return 0;
}
function checkDeclarationsAnyOrder(block, props, msg) {
let actual = [];
for (let name of block) {
let value = block.getPropertyValue(name);
let priority = block.getPropertyPriority(name);
actual.push({name, value, priority});
}
actual.sort(compareByName);
let expected = Array.from(props);
expected.sort(compareByName);
assert_object_equals(actual, expected, "Declaration block content should match " + msg);
}
function longhand(name, value, priority="") {
return {name, value, priority};
}
function* shorthand(name, value, priority="") {
for (let subprop of SUBPROPS[name]) {
yield longhand(subprop, value, priority);
}
}
const SUBPROPS = {
"margin": ["margin-top", "margin-right", "margin-bottom", "margin-left"],
"padding": ["padding-top", "padding-right", "padding-bottom", "padding-left"],
};
test(function() {
let expectedDecls = [
longhand("top", "1px"),
longhand("bottom", "2px"),
longhand("left", "3px", "important"),
longhand("right", "4px"),
];
let block = generateCSSDeclBlock(expectedDecls);
checkDeclarationsAnyOrder(block, expectedDecls, "in initial block");
block.setProperty("top", "5px", "important");
expectedDecls[0] = longhand("top", "5px", "important");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property");
block.setProperty("bottom", "2px");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with identical value");
block.setProperty("left", "3px");
expectedDecls[2].priority = "";
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with different priority");
block.setProperty("float", "none");
expectedDecls.push(longhand("float", "none"));
checkDeclarationsAnyOrder(block, expectedDecls, "after setting non-existing property");
}, "setProperty with longhand should update only the declaration being set");
test(function() {
let expectedDecls = [
longhand("top", "1px"),
longhand("bottom", "2px"),
longhand("left", "3px", "important"),
longhand("right", "4px"),
];
let block = generateCSSDeclBlock(expectedDecls);
checkDeclarationsAnyOrder(block, expectedDecls, "in initial block");
block.top = "5px";
expectedDecls[0] = longhand("top", "5px");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property");
block.bottom = "2px";
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with identical value");
block.left = "3px";
expectedDecls[2].priority = "";
checkDeclarationsAnyOrder(block, expectedDecls, "after setting existing property with different priority");
block.float = "none";
expectedDecls.push(longhand("float", "none"));
checkDeclarationsAnyOrder(block, expectedDecls, "after setting non-existing property");
}, "property setter should update only the declaration being set");
test(function() {
let expectedDecls = [
...shorthand("margin", "1px"),
longhand("top", "2px"),
...shorthand("padding", "3px", "important"),
];
let block = generateCSSDeclBlock(expectedDecls);
checkDeclarationsAnyOrder(block, expectedDecls, "in initial block");
block.setProperty("margin", "4px");
for (let i = 0; i < 4; i++) {
expectedDecls[i].value = "4px";
}
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand");
block.setProperty("margin", "4px");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with identical value");
block.setProperty("padding", "3px");
for (let i = 5; i < 9; i++) {
expectedDecls[i].priority = "";
}
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with different priority");
block.setProperty("margin-bottom", "5px", "important");
expectedDecls[2] = longhand("margin-bottom", "5px", "important");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting a longhand in an existing shorthand");
}, "setProperty with shorthand should update only the declarations being set");
test(function() {
let expectedDecls = [
...shorthand("margin", "1px"),
longhand("top", "2px"),
...shorthand("padding", "3px", "important"),
];
let block = generateCSSDeclBlock(expectedDecls);
checkDeclarationsAnyOrder(block, expectedDecls, "in initial block");
block.margin = "4px";
for (let i = 0; i < 4; i++) {
expectedDecls[i].value = "4px";
}
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand");
block.margin = "4px";
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with identical value");
block.padding = "3px";
for (let i = 5; i < 9; i++) {
expectedDecls[i].priority = "";
}
checkDeclarationsAnyOrder(block, expectedDecls, "after setting an existing shorthand with different priority");
block.marginBottom = "5px";
expectedDecls[2] = longhand("margin-bottom", "5px");
checkDeclarationsAnyOrder(block, expectedDecls, "after setting a longhand in an existing shorthand");
}, "longhand property setter should update only the decoarations being set");
</script>
|