Adding in CSS and HTML linting. Fixes 72

This commit is contained in:
Jonathan Kingston 2017-01-25 16:52:27 +00:00
parent 1e6b684915
commit 71001050b4
7 changed files with 231 additions and 105 deletions

8
.htmllintrc Normal file
View file

@ -0,0 +1,8 @@
{
"plugins": [],
"id-class-style": "dash",
"indent-style": "spaces",
"indent-width": 2,
"attr-name-ignore-regex": "http-equiv|data-*"
}

18
.stylelintrc Normal file
View file

@ -0,0 +1,18 @@
{
"extends": "stylelint-config-standard",
"ignoreFiles": ["webextension/css/*.min.css"],
"rules": {
"declaration-block-no-duplicate-properties": true,
"declaration-block-properties-order": "alphabetical",
"property-blacklist": [
"/height/",
"/width/",
"/top/",
"/bottom/",
"padding",
"margin"
]
}
}

View file

@ -652,21 +652,22 @@ ContainerWindow.prototype = {
const mouseoutHandle = (e) => {
let el = e.target;
do {
if (el == this._panelElement ||
el == button ||
el == overflowButton) {
while(el) {
if (el === this._panelElement ||
el === button ||
el === overflowButton) {
this._createTimeout();
return;
}
} while(el = el.parentElement);
el = el.parentElement;
}
};
[button, overflowButton].forEach((buttonElement) => {
buttonElement.addEventListener("mouseover", () => {
showPopup(buttonElement);
});
buttonElement.addEventListener("click", _ => {
buttonElement.addEventListener("click", () => {
this.hidePanel();
});
buttonElement.addEventListener("mouseout", mouseoutHandle);

View file

@ -12,8 +12,11 @@
"addons-linter": "^0.15.14",
"eslint": "^3.12.2",
"eslint-plugin-promise": "^3.4.0",
"htmllint-cli": "^0.0.5",
"jpm": "^1.2.2",
"npm-run-all": "^4.0.0"
"npm-run-all": "^4.0.0",
"stylelint": "^7.7.1",
"stylelint-config-standard": "^15.0.1"
},
"engines": {
"firefox": ">=50.0"
@ -31,7 +34,9 @@
},
"scripts": {
"lint": "npm-run-all lint:*",
"lint:js": "eslint .",
"lint:addon": "addons-linter webextension --self-hosted"
"lint:addon": "addons-linter webextension --self-hosted",
"lint:css": "stylelint webextension/css/*.css",
"lint:html": "htmllint webextension/*.html",
"lint:js": "eslint ."
}
}

View file

@ -1,7 +1,7 @@
body {
min-inline-size: 200px;
max-inline-size: 400px;
inline-size: 264px;
max-inline-size: 400px;
min-inline-size: 200px;
}
table {
@ -28,12 +28,14 @@ table {
}
.onboarding {
margin: 16px;
min-block-size: 480px;
align-items: center;
display: flex;
flex-flow: column;
align-items: center;
margin-block-end: 16px;
margin-block-start: 16px;
margin-inline-end: 16px;
margin-inline-start: 16px;
min-block-size: 480px;
}
.onboarding h3 {
@ -51,20 +53,23 @@ table {
.popup-bumper {
inline-size: 100%;
padding: .5em;
padding-block-end: 0.5em;
padding-block-start: 0.5em;
padding-inline-end: 0.5em;
padding-inline-start: 0.5em;
}
.panel-header {
align-items: center;
block-size: 54px;
display: flex;
align-items: center;
}
.panel-header-text {
font-weight: lighter;
font-size: 16px;
margin-bottom: 0;
color: #4a4a4a;
font-size: 16px;
font-weight: lighter;
margin-block-end: 0;
}
.panel-header-button {
@ -72,56 +77,64 @@ table {
}
.icon {
max-inline-size: 16px;
block-size: 16px;
max-inline-size: 16px;
}
table.unstriped tbody tr {
border-bottom: 1px solid #f1f1f1;
background-color: #fefefe;
border-block-end: 1px solid #f1f1f1;
}
.userContext-icon {
/* .userContext-icon is used natively, Bug 1333811 was raised to fix */
.userContext-icon,
.usercontext-icon {
background-image: var(--identity-icon);
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
filter: url('/img/filters.svg#fill');
fill: var(--identity-icon-color);
inline-size: 20px;
block-size: 20px;
fill: var(--identity-icon-color);
filter: url('/img/filters.svg#fill');
inline-size: 20px;
padding-left: 20px;
padding-right: 10px;
}
.container-panel-row:hover .userContext-icon {
.container-panel-row:hover .usercontext-icon {
background-image: url('/img/container-newtab.svg');
filter: url('/img/filters.svg#fill');
fill: 'gray';
filter: url('/img/filters.svg#fill');
}
.edit-identities {
background: #DCDBDC;
background: #dcdbdc;
}
.panel-footer {
align-items: center;
background: #efefef;
color: #000000;
block-size: 54px;
color: #000;
display: flex;
font-size: 13px;
block-size: 54px;
inline-size: 100%;
}
.footer-columns {
margin: 0;
padding: 0;
margin-block-end: 0;
margin-block-start: 0;
margin-inline-end: 0;
margin-inline-start: 0;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 0;
padding-inline-start: 0;
}
.footer-button {
margin-bottom: 0;
border-radius: 0;
margin-block-end: 0;
}
.cancel-button {
@ -129,14 +142,66 @@ table.unstriped tbody tr {
}
.edit-containers-text {
text-align: center;
border-inline-end: solid 1px #d8d8d8;
text-align: center;
}
.edit-containers-text a {
color: #0a0a0a;
}
.edit-container-panel [type="radio"] {
display: inline;
margin-inline-start: -17px;
text-indent: -999999px;
}
.edit-container-panel [type="radio"]:first-child {
margin-inline-start: 0;
}
.edit-container-panel label {
background: #fff;
block-size: 20px;
filter: none;
inline-size: 20px;
margin-block-end: 0;
margin-block-start: 0;
margin-inline-end: 0;
margin-inline-start: 0;
offset-inline-start: -18px;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 0;
padding-inline-start: 0;
position: relative;
}
.edit-container-panel [type="radio"]:checked + label {
outline: 1px solid grey;
-moz-outline-radius: 100%;
}
.edit-container-panel label::before {
background: var(--identity-icon);
background-position: center center;
background-repeat: no-repeat;
background-size: calc(100% - 4px);
block-size: calc(100% - 2px);
border: unset;
fill: var(--identity-icon-color);
filter: url('/img/filters.svg#fill');
inline-size: calc(100% - 2px);
margin-block-end: 1px;
margin-block-start: 1px;
margin-inline-end: 1px;
margin-inline-start: 1px;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 0;
padding-inline-start: 0;
}
[data-identity-color="blue"] {
--identity-tab-color: #0996f8;
--identity-icon-color: #00a7e0;
@ -149,7 +214,7 @@ table.unstriped tbody tr {
[data-identity-color="green"] {
--identity-tab-color: #57bd35;
--identity-icon-color: #7dc14c;
--identity-icon-color: #7dc14c;
}
[data-identity-color="yellow"] {
@ -198,17 +263,23 @@ table.unstriped tbody tr {
}
.container-info-panel-header {
block-size: 33px;
display: flex;
align-items: center;
block-size: 33px;
border-block-end: 1px solid #ebebeb;
display: flex;
margin-block-end: 10px;
padding: 0 20px;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 20px;
padding-inline-start: 20px;
}
.container-info-panel-hide {
margin-bottom: 8px;
padding: 0 20px;
margin-block-end: 8px;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 20px;
padding-inline-start: 20px;
}
.container-info-panel-hideorshow-icon {
@ -218,7 +289,10 @@ table.unstriped tbody tr {
.container-info-panel-movetabs {
border-block-end: 1px solid #ebebeb;
margin-block-end: 10px;
padding: 0 20px;
padding-block-end: 0;
padding-block-start: 0;
padding-inline-end: 20px;
padding-inline-start: 20px;
}
.clickable {
@ -226,24 +300,24 @@ table.unstriped tbody tr {
}
.edit-containers-panel-footer a {
color: #ffffff;
color: #fff;
}
.edit-containers-exit-text {
display: flex;
align-items: center;
background: #248aeb;
block-size: 100%;
color: #ffffff;
color: #fff;
display: flex;
justify-content: center;
}
.choose-color-icon {
padding-inline-start: 17px;
padding-inline-end: 7px;
padding-inline-start: 17px;
}
.scrollable {
max-block-size: 480px;
overflow: auto;
max-height: 480px;
}

View file

@ -5,6 +5,9 @@
const CONTAINER_HIDE_SRC = "/img/container-hide.svg";
const CONTAINER_UNHIDE_SRC = "/img/container-unhide.svg";
const DEFAULT_COLOR = "blue";
const DEFAULT_ICON = "circle";
// List of panels
const P_ONBOARDING_1 = "onboarding1";
const P_ONBOARDING_2 = "onboarding2";
@ -303,35 +306,37 @@ Logic.registerPanel(P_CONTAINER_INFO, {
return browser.runtime.sendMessage({
method: "getTabs",
userContextId: identity.userContextId,
}).then(tabs => {
// For each one, let's create a new line.
const fragment = document.createDocumentFragment();
for (let tab of tabs) { // eslint-disable-line prefer-const
const tr = document.createElement("tr");
fragment.appendChild(tr);
tr.classList.add("container-info-tab");
tr.innerHTML = `
<td><img class="icon" src="${tab.favicon}" /></td>
<td>${tab.title}</td>`;
}).then(this.buildInfoTable);
},
// On click, we activate this tab. But only if this tab is active.
if (tab.active) {
tr.classList.add("clickable");
tr.addEventListener("click", () => {
browser.runtime.sendMessage({
method: "showTab",
tabId: tab.id,
}).then(() => {
window.close();
}).catch(() => {
window.close();
});
buildInfoTable(tabs) {
// For each one, let's create a new line.
const fragment = document.createDocumentFragment();
for (let tab of tabs) { // eslint-disable-line prefer-const
const tr = document.createElement("tr");
fragment.appendChild(tr);
tr.classList.add("container-info-tab");
tr.innerHTML = `
<td><img class="icon" src="${tab.favicon}" /></td>
<td>${tab.title}</td>`;
// On click, we activate this tab. But only if this tab is active.
if (tab.active) {
tr.classList.add("clickable");
tr.addEventListener("click", () => {
browser.runtime.sendMessage({
method: "showTab",
tabId: tab.id,
}).then(() => {
window.close();
}).catch(() => {
window.close();
});
}
});
}
}
document.getElementById("container-info-table").appendChild(fragment);
});
document.getElementById("container-info-table").appendChild(fragment);
},
});
@ -406,6 +411,8 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
// This method is called when the object is registered.
initialize() {
this.initializeRadioButtons();
document.querySelector("#edit-container-panel-back-arrow").addEventListener("click", () => {
Logic.showPreviousPanel();
});
@ -416,12 +423,13 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
document.querySelector("#edit-container-ok-link").addEventListener("click", () => {
const identity = Logic.currentIdentity();
const formValues = new FormData(document.getElementById("edit-container-panel-form"));
browser.runtime.sendMessage({
method: identity.userContextId ? "updateIdentity" : "createIdentity",
userContextId: identity.userContextId || 0,
name: document.getElementById("edit-container-panel-name-input").value || Logic.generateIdentityName(),
icon: this._randomIcon(),
color: this._randomColor(),
icon: formValues.get("container-icon") || DEFAULT_ICON,
color: formValues.get("container-color") || DEFAULT_COLOR,
}).then(() => {
return Logic.refreshIdentities();
}).then(() => {
@ -432,27 +440,46 @@ Logic.registerPanel(P_CONTAINER_EDIT, {
});
},
initializeRadioButtons() {
const colorRadioTemplate = (containerColor) => {
return `<input type="radio" value="${containerColor}" name="container-color" id="edit-container-panel-choose-color-${containerColor}" />
<label for="edit-container-panel-choose-color-${containerColor}" class="usercontext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="${containerColor}">`;
};
const colors = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple" ];
const colorRadioFieldset = document.getElementById("edit-container-panel-choose-color");
colors.forEach((containerColor) => {
const templateInstance = document.createElement("span");
templateInstance.innerHTML = colorRadioTemplate(containerColor);
colorRadioFieldset.appendChild(templateInstance);
});
const iconRadioTemplate = (containerIcon) => {
return `<input type="radio" value="${containerIcon}" name="container-icon" id="edit-container-panel-choose-icon-${containerIcon}" />
<label for="edit-container-panel-choose-icon-${containerIcon}" class="usercontext-icon choose-color-icon" data-identity-color="grey" data-identity-icon="${containerIcon}">`;
};
const icons = ["fingerprint", "briefcase", "dollar", "cart", "circle"];
const iconRadioFieldset = document.getElementById("edit-container-panel-choose-icon");
icons.forEach((containerIcon) => {
const templateInstance = document.createElement("span");
templateInstance.innerHTML = iconRadioTemplate(containerIcon);
iconRadioFieldset.appendChild(templateInstance);
});
},
// This method is called when the panel is shown.
prepare() {
const identity = Logic.currentIdentity();
document.querySelector("#edit-container-panel-name-input").value = identity.name || "";
// FIXME: color and icon must be set. But we need the UI first.
[...document.querySelectorAll("[name='container-color']")].forEach(colorInput => {
colorInput.checked = colorInput.value === identity.color;
});
[...document.querySelectorAll("[name='container-icon']")].forEach(iconInput => {
iconInput.checked = iconInput.value === identity.image;
});
return Promise.resolve(null);
},
// These 2 methods are for debugging only. We should remove them when we
// finish the UI.
_randomIcon() {
const images = ["fingerprint", "briefcase", "dollar", "cart", "cirlce"];
return images[Math.floor(Math.random() * images.length)];
},
_randomColor() {
const colors = ["blue", "turquoise", "green", "yellow", "orange", "red", "pink", "purple" ];
return colors[Math.floor(Math.random() * colors.length)];
},
});
// P_CONTAINER_DELETE: Delete a container.

View file

@ -56,10 +56,10 @@
<div class="small-2 columns panel-back-arrow clickable" id="close-container-info-panel">&laquo;</div>
<div class="small-10 columns">
<div class="row container-info-panel-header">
<span class="userContext-icon" id="container-info-icon" data-identity-icon="" data-identity-color=""></span>
<span class="usercontext-icon" id="container-info-icon"></span>
<h3 id="container-info-name" class="panel-header-text"></h3>
</div>
<div class="row container-info-panel-hide container-info-has-tabs clickable" id="container-info-hideorshow" data-user-context-id="">
<div class="row container-info-panel-hide container-info-has-tabs clickable" id="container-info-hideorshow">
<img id="container-info-hideorshow-icon" alt="Hide Container icon" src="/img/container-hide.svg" class="icon container-info-panel-hideorshow-icon"/><span id="container-info-hideorshow-label">Hide this container</span><br/>
</div>
<div class="row container-info-panel-movetabs container-info-has-tabs clickable" id="container-info-movetabs">
@ -104,27 +104,20 @@
&laquo;
</div>
<div class="small-10 columns">
<form>
<form id="edit-container-panel-form">
<p>
<label>Name</label>
<label for="edit-container-panel-name-input">Name</label>
<input type="text" name="container-name" id="edit-container-panel-name-input"/>
</p>
<p>
<label>Choose a color</label>
<div id="edit-container-panel-choose-color">
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="blue"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="turquoise"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="green"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="yellow"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="orange"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="red"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="pink"></span>
<span class="userContext-icon choose-color-icon" data-identity-icon="circle" data-identity-color="purple"></span>
</div>
<fieldset id="edit-container-panel-choose-color">
<legend>Choose a color</legend>
</fieldset>
</p>
<p>
<label>Choose an icon</label>
<input type="text" />
<fieldset id="edit-container-panel-choose-icon">
<legend>Choose an icon</legend>
</fieldset>
</p>
</form>
<div class="row">
@ -143,7 +136,7 @@
<div class="row">
<div class="small-12 columns">
<div class="row container-info-panel-header">
<span class="userContext-icon" id="delete-container-icon" data-identity-icon="" data-identity-color=""></span>
<span class="usercontext-icon" id="delete-container-icon"></span>
<h3 id="delete-container-name" class="panel-header-text"></h3>
</div>
<div class="row delete-container-confirm">