Saving work time to localStorage for safe page refresh, some markup & style fixes

parent 3777f2c8
...@@ -192,5 +192,3 @@ var focusManager = { ...@@ -192,5 +192,3 @@ var focusManager = {
focusFirstInElement: focusFirstInElement, focusFirstInElement: focusFirstInElement,
focusLastInElement: focusLastInElement focusLastInElement: focusLastInElement
}; };
export.default = focusManager;
// focusManager
function isAncestor(ancestor, descendant) {
var element = descendant;
while (element) {
if (element === ancestor) {
return true;
}
element = element.parentElement;
}
return false;
}
function isDisabled(element) {
return element.disabled === true;
}
function isFocusable(element) {
return Boolean(element) && element.tabIndex >= 0 && !isDisabled(element);
}
function makeFocusable(element) {
// A tabIndex is needed to make the element focusable
// A tabIndex of -1 means that the element is only programmatically focusable
if (isDisabled(element)) {
element.disabled = false;
}
if (!isFocusable(element)) {
element.tabIndex = -1;
}
}
// Find the first focusable element.
// The candidates are the element and it's descendants.
// The search is performed depth-first.
function findFirstFocusableElement(element) {
if (isFocusable(element)) {
return element;
}
var children = element.children;
var length = children.length;
var child;
var focusableDescendant;
for (var i = 0; i < length; i += 1) {
child = children[i];
focusableDescendant = findFirstFocusableElement(child);
if (focusableDescendant) {
return focusableDescendant;
}
}
return null;
}
// Find the first focusable element.
// The candidates are the element and it's descendants.
// The search is performed depth-first.
function findLastFocusableElement(element) {
var children = element.children;
var length = children.length;
var child;
var focusableDescendant;
for (var i = length -1; i >= 0; i -= 1) {
child = children[i];
focusableDescendant = findLastFocusableElement(child);
if (focusableDescendant) {
return focusableDescendant;
}
}
if (isFocusable(element)) {
return element;
}
return null;
}
function focus(element) {
makeFocusable(element);
element.focus();
state.lastFocus = element;
}
function resolveFocus(parent, defaultFocus) {
var focusElement;
if (defaultFocus) {
focusElement = defaultFocus;
} else {
focusElement = findFirstFocusableElement(parent) || parent;
if (focusElement === state.lastFocus) {
focusElement = findLastFocusableElement(parent) || parent;
}
}
focus(focusElement);
}
function focusFirstInElement(element) {
var focusElement = findFirstFocusableElement(element) || element;
focus(focusElement);
}
function focusLastInElement(element) {
var focusElement = findLastFocusableElement(element) || element;
focus(focusElement);
}
// State is kept is these variables.
// Since only one modal dialog can capture focus at a time the state is a singleton.
var state = {
eventListenerArguments: null,
eventListenerContext: null,
lastFocus: null
};
function releaseModalFocus(focusElement) {
var eventListenerContext = state.eventListenerContext;
var eventListenerArguments = state.eventListenerArguments;
if (eventListenerContext && eventListenerArguments) {
eventListenerContext.removeEventListener.apply(eventListenerContext, eventListenerArguments);
}
// Reset the state object
state.eventListenerContext = null;
state.eventListenerArguments = null;
state.lastFocus = null;
if (focusElement) {
focusElement.focus();
}
}
// Keep focus inside the modal
function restrictFocus(modal, focusedElement) {
if (isAncestor(modal, focusedElement)) {
state.lastFocus = focusedElement;
} else {
resolveFocus(modal);
}
}
// modal, the element in which to contain focus
// focusElement (optional), the element inside the modal to focus when opening
// backgroundElement (optional), All focus events within this element are redirected to the modal. Defaults to document
function captureModalFocus(modal, focusElement, backgroundElement) {
// without a modal there is nothing to capture
if (!modal) {
return null;
}
// If any focus is already being captured, release it now
releaseModalFocus();
// focus the modal so the user knows it was opened
resolveFocus(modal, focusElement);
// Whenever an element outside of the modal is focused, the modal is focused instead
function focusCallback(evnt) {
restrictFocus(modal, evnt.target);
}
// The focus event does not bubble
// however it can be captured on an ancestor element
// by setting useCapture to true
var eventListenerContext = backgroundElement || document;
var eventListenerArguments = ["focus", focusCallback, true];
// Save the eventListener data in the state object so it can be removed later
// by the releaseModalFocus function
state.eventListenerContext = eventListenerContext;
state.eventListenerArguments = eventListenerArguments;
eventListenerContext.addEventListener.apply(eventListenerContext, eventListenerArguments);
}
var focusManager = {
capture: captureModalFocus,
release: releaseModalFocus,
focusFirstInElement: focusFirstInElement,
focusLastInElement: focusLastInElement
};
///////////////////////////////////////////////
//Номер баги //Номер баги
var bugId = getIdFromUrl() || getBugIdFromField(); var bugId = getIdFromUrl() || getBugIdFromField();
...@@ -209,7 +13,7 @@ var protocol = window.location.protocol; ...@@ -209,7 +13,7 @@ var protocol = window.location.protocol;
var changed_remain = 0; var changed_remain = 0;
//Создание баги //Создание баги
var etersoft_create = window.location.href.search('enter') !== -1 ? 1 : 0; var etersoft_create = window.location.href.search("enter") !== -1 ? 1 : 0;
// Объект таймера, создается при инициализации // Объект таймера, создается при инициализации
// Подробнее про таймер см. timer_common.js // Подробнее про таймер см. timer_common.js
...@@ -293,92 +97,110 @@ function isworker() { ...@@ -293,92 +97,110 @@ function isworker() {
return email == assignemail; return email == assignemail;
} }
window.addEventListener('load', function () { window.addEventListener("load", function() {
function getTimespentValue() { function getTimespentValue() {
let timespent = document.querySelector("#timespent").value; let timespent = document.querySelector("#timespent").value;
let timespentValue = timespent.split(":"); let timespentValue = timespent.split(":");
// let's calc how many time is spent in minutes // let's calc how many time is spent in minutes
let hours = parseInt(timespentValue[0]) * 60; let hours = parseInt(timespentValue[0]) * 60;
let minutes = parseInt(timespentValue[1]); let minutes = parseInt(timespentValue[1]);
let seconds = Math.round(parseInt(timespentValue[2]) / 60); let seconds = Math.round(parseInt(timespentValue[2]) / 60);
timespentValue = hours + minutes + seconds; timespentValue = hours + minutes + seconds;
return timespentValue; return timespentValue;
} }
// add listener for comment commit
//let commitBtn = document.querySelector("#commit");
let openButton = document.querySelector("#commit");
let closeButton = document.querySelectorAll("#timeQuestionDiv .close");
let dialog = document.querySelector("#timeQuestionDiv");
openButton.addEventListener("click", function(event) {
// cancel form submiting
event.preventDefault();
let timespentValue = getTimespentValue(); // add listener for comment commit
//let commitBtn = document.querySelector("#commit");
let openButton = document.querySelector("#commit");
let closeButton = document.querySelectorAll("#timeQuestionDiv .close");
let dialog = document.querySelector("#timeQuestionDiv");
dialog.style.display = "block"; openButton.addEventListener("click", function(event) {
focusManager.capture(dialog); // cancel form submiting
event.preventDefault();
// write work time in input value let timespentValue = getTimespentValue();
document.querySelector("#realworktime").value = timespentValue;
document.querySelector("#saveTime").dataset['time'] = timespentValue;
});
document.querySelector("#realworktime").addEventListener("change", function() { dialog.style.display = "block";
document.querySelector("#saveTime").dataset["time"] = document.querySelector("#realworktime").value; focusManager.capture(dialog);
console.log('time changed:', document.querySelector("#saveTime").dataset["time"]);
});
document.querySelector("#realworktime").addEventListener("paste", function() { // write work time in input value
document.querySelector("#saveTime").dataset["time"] = document.querySelector("#realworktime").value; document.querySelector("#realworktime").value =
console.log('time changed:', document.querySelector("#saveTime").dataset["time"]); localStorage.time === undefined ? timespentValue : localStorage.time;
}); document.querySelector("#saveTime").dataset["time"] = timespentValue;
});
document
.querySelector("#realworktime")
.addEventListener("change", function() {
document.querySelector("#saveTime").dataset["time"] = this.value;
localStorage.time = this.value;
console.log(
"time changed:",
document.querySelector("#saveTime").dataset["time"]
);
});
document.querySelector("#realworktime").addEventListener("paste", function() {
document.querySelector("#saveTime").dataset["time"] = this.value;
localStorage.time = this.value;
console.log(
"time changed:",
document.querySelector("#saveTime").dataset["time"]
);
});
// add listener for time commit // add listener for time commit
let btn = document.querySelector("#saveTime"); let btn = document.querySelector("#saveTime");
btn.addEventListener("click", function(event) { btn.addEventListener("click", function(event) {
// cancel form submiting // cancel form submiting
event.preventDefault(); event.preventDefault();
// let's calc time for #work_time input // let's calc time for #work_time input
let workTime = parseInt(document.querySelector('#realworktime').value); let workTime = parseInt(document.querySelector("#realworktime").value);
workTime = workTime === parseInt(btn.dataset["time"]) ? parseInt(btn.dataset["time"]) : workTime; workTime =
workTime === parseInt(btn.dataset["time"])
? parseInt(btn.dataset["time"])
: workTime;
workTime = workTime > 0 ? workTime : 1; workTime = workTime > 0 ? workTime : 1;
let workTimeValue = Math.ceil(workTime / 60 * 100) / 100; let workTimeValue = Math.ceil((workTime / 60) * 100) / 100;
let productiveTime = parseInt(document.querySelector('#ProductTime').value); let productiveTime = parseInt(document.querySelector("#ProductTime").value);
productiveTime = productiveTime > 0 ? productiveTime : 1; productiveTime = productiveTime > 0 ? productiveTime : 1;
let productiveTimeValue = Math.ceil(productiveTime / 60 * 100) / 100; let productiveTimeValue = Math.ceil((productiveTime / 60) * 100) / 100;
document.querySelector("#work_time").value = workTimeValue; document.querySelector("#work_time").value = workTimeValue;
document.querySelector("#productive_time").value = productiveTimeValue; document.querySelector("#productive_time").value = productiveTimeValue;
// now we ready for submiting all forms // now we ready for submiting all forms
let mainCommitBtn = document.querySelector("#commit_top"); let mainCommitBtn = document.querySelector("#commit_top");
// check comment before submit // check comment before submit
let comment = document.querySelector("#comment").value; let comment = document.querySelector("#comment").value;
if (comment.length !== 0) { if (comment.length !== 0) {
if (comment.length < 9) { if (comment.length < 9) {
alert("Слишком короткий комментарий"); alert("Слишком короткий комментарий");
} } else if (productiveTimeValue > 8 || workTimeValue > 8) {
else if (productiveTimeValue > 8 || workTimeValue > 8) { alert(
alert("Недопустимо указывать отработанное/продуктивное время более восьми часов. Правильным следованием рабочему процессу было бы выполнение работы по частям, о каждой из которых будет написано отдельно."); "Недопустимо указывать отработанное/продуктивное время более восьми часов. Правильным следованием рабочему процессу было бы выполнение работы по частям, о каждой из которых будет написано отдельно."
} );
else if (productiveTimeValue > 2 && comment.length < productiveTimeValue * 60) { } else if (
alert("Недопустимо коротко комментировать длительные работы. Мы ожидаем не менее 60 символов на каждый указанный час."); productiveTimeValue > 2 &&
} comment.length < productiveTimeValue * 60
else if (productiveTimeValue > workTimeValue) { ) {
alert(
"Недопустимо коротко комментировать длительные работы. Мы ожидаем не менее 60 символов на каждый указанный час."
);
} else if (productiveTimeValue > workTimeValue) {
alert("Продуктивное время не может быть больше отработанного!"); alert("Продуктивное время не может быть больше отработанного!");
} else { } else {
let bugForm = etersoft_create === 1 ? "#Create" : "#changeform"; let bugForm = etersoft_create === 1 ? "#Create" : "#changeform";
document.querySelector(bugForm).submit(); document.querySelector(bugForm).submit();
timer.clear(); timer.clear();
localStorage.removeItem("time");
} }
} else { } else {
alert("Поле комментария не может быть пустым!"); alert("Поле комментария не может быть пустым!");
...@@ -390,29 +212,29 @@ let btn = document.querySelector("#saveTime"); ...@@ -390,29 +212,29 @@ let btn = document.querySelector("#saveTime");
function validate(evt) { function validate(evt) {
let theEvent = evt || window.event; let theEvent = evt || window.event;
let key = theEvent.keyCode || theEvent.which; let key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode( key ); key = String.fromCharCode(key);
let regex = /[0-9\s]/; let regex = /[0-9\s]/;
if( !regex.test(key) ) { if (!regex.test(key)) {
theEvent.returnValue = false; theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault(); if (theEvent.preventDefault) theEvent.preventDefault();
} }
} }
document.querySelector('#realworktime').onkeypress = function() { document.querySelector("#realworktime").onkeypress = function() {
validate(event); validate(event);
} };
document.querySelector('#realworktime').onpaste = function() { document.querySelector("#realworktime").onpaste = function() {
validate(event); validate(event);
} };
document.querySelector('#ProductTime').onkeypress = function() { document.querySelector("#ProductTime").onkeypress = function() {
validate(event); validate(event);
} };
document.querySelector('#ProductTime').onpaste = function() { document.querySelector("#ProductTime").onpaste = function() {
validate(event); validate(event);
} };
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
......
...@@ -145,7 +145,7 @@ fieldset { ...@@ -145,7 +145,7 @@ fieldset {
resize: none; resize: none;
} }
.workTime button[type="submit"], .workTime__button { .workTime button[type="submit"], .workTime__button, .workTime__button--save {
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
border: none; border: none;
...@@ -155,7 +155,7 @@ fieldset { ...@@ -155,7 +155,7 @@ fieldset {
font-size: 15px; font-size: 15px;
} }
.workTime__button{ .workTime__button {
margin-left: 5px; margin-left: 5px;
} }
...@@ -176,45 +176,34 @@ fieldset { ...@@ -176,45 +176,34 @@ fieldset {
.workTime__input:focus, .workTime__input:focus,
.workTime__button:focus, .workTime__button:focus,
.workTime__button--save:focus,
.close:focus { .close:focus {
outline: 2px solid rgba(82, 157, 236, 0.8); outline: 2px solid rgba(82, 157, 236, 0.8);
box-sizing: border-box;
} }
.workTimeInner{ .workTimeInner {
display: flex; display: flex;
margin-top: 0.5rem;
} }
.close { .close {
position: absolute; position: absolute;
right: 10px; right: 5px;
top: 10px; top: 0;
width: 25px;
height: 25px;
opacity: 0.4; opacity: 0.4;
cursor: pointer; cursor: pointer;
font-size: 48px;
border: none;
box-sizing: border-box;
background: none;
text-decoration: none;
} }
.close:hover { .close:hover {
opacity: 1; opacity: 1;
} }
.close:before, .close:after {
position: absolute;
left: 15px;
content: ' ';
height: 25px;
width: 2px;
background-color: #000;
}
.close:before {
transform: rotate(45deg);
}
.close:after {
transform: rotate(-45deg);
}
::-webkit-input-placeholder { ::-webkit-input-placeholder {
color: #888; color: #888;
} }
......
...@@ -16,11 +16,10 @@ ...@@ -16,11 +16,10 @@
<div class="container"> <div class="container">
<div class="workTime"> <div class="workTime">
<h3>Укажите отработанное время</h3> <h3>Укажите отработанное время</h3>
<h4>Отслеживайте корректность оставшегося времени.</h4>
<fieldset> <fieldset>
Отработанное время: Отработанное время:
<div class="workTimeInner"> <div class="workTimeInner">
<input class="workTime__input" id="realworktime" name="realworktime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="1" required autofocus> <input class="workTime__input" id="realworktime" name="realworktime" data-time="" placeholder="в минутах" title="Время в минутах" type="text" tabindex="1" required autofocus>
<button class="workTime__button" data-time="1" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="2">1</button> <button class="workTime__button" data-time="1" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="2">1</button>
<button class="workTime__button" data-time="5" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="3">5</button> <button class="workTime__button" data-time="5" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="3">5</button>
<button class="workTime__button" data-time="15" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="4">15</button> <button class="workTime__button" data-time="15" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="4">15</button>
...@@ -30,7 +29,7 @@ ...@@ -30,7 +29,7 @@
<fieldset> <fieldset>
Продуктивное время: Продуктивное время:
<div class="workTimeInner"> <div class="workTimeInner">
<input id="ProductTime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="6" required> <input class="workTime__input" id="ProductTime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="6" required>
<button class="workTime__button" data-time="1" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="7">1</button> <button class="workTime__button" data-time="1" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="7">1</button>
<button class="workTime__button" data-time="5" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="8">5</button> <button class="workTime__button" data-time="5" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="8">5</button>
<button class="workTime__button" data-time="15" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="9">15</button> <button class="workTime__button" data-time="15" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="9">15</button>
...@@ -38,12 +37,13 @@ ...@@ -38,12 +37,13 @@
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<button class="workTime__button" id="saveTime" tabindex="11">Сохранить</button> <button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button>
</fieldset> </fieldset>
<a onclick="closeDiv();" class="close" tabindex="12"></a> <button onclick="closeDiv();" class="close" tabindex="12">&times;</button>
</div> </div>
</div> </div>
</div> </div>
<script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_11_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_11_2017"></script>
...@@ -16,34 +16,34 @@ ...@@ -16,34 +16,34 @@
<div class="container"> <div class="container">
<div class="workTime"> <div class="workTime">
<h3>Укажите отработанное время</h3> <h3>Укажите отработанное время</h3>
<h4>Отслеживайте корректность оставшегося времени.</h4>
<fieldset> <fieldset>
Отработанное время: Отработанное время:
<div class="workTimeInner"> <div class="workTimeInner">
<input class="workTime__input" id="realworktime" name="realworktime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="1" required autofocus> <input class="workTime__input" id="realworktime" name="realworktime" data-time="" placeholder="в минутах" title="Время в минутах" type="text" tabindex="1" required>
<button class="workTime__button" data-time="1" onclick="document.querySelector('#realworktime').value=this.dataset['time']">1</button> <button class="workTime__button" data-time="1" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="2">1</button>
<button class="workTime__button" data-time="5" onclick="document.querySelector('#realworktime').value=this.dataset['time']">5</button> <button class="workTime__button" data-time="5" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="3">5</button>
<button class="workTime__button" data-time="15" onclick="document.querySelector('#realworktime').value=this.dataset['time']">15</button> <button class="workTime__button" data-time="15" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="4">15</button>
<button class="workTime__button" data-time="30" onclick="document.querySelector('#realworktime').value=this.dataset['time']">30</button> <button class="workTime__button" data-time="30" onclick="document.querySelector('#realworktime').value=this.dataset['time']" tabindex="5">30</button>
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
Продуктивное время: Продуктивное время:
<div class="workTimeInner"> <div class="workTimeInner">
<input id="ProductTime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="2" required> <input class="workTime__input" id="ProductTime" placeholder="в минутах" title="Время в минутах" type="text" tabindex="6" required>
<button class="workTime__button" data-time="1" onclick="document.querySelector('#ProductTime').value=this.dataset['time']">1</button> <button class="workTime__button" data-time="1" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="7">1</button>
<button class="workTime__button" data-time="5" onclick="document.querySelector('#ProductTime').value=this.dataset['time']">5</button> <button class="workTime__button" data-time="5" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="8">5</button>
<button class="workTime__button" data-time="15" onclick="document.querySelector('#ProductTime').value=this.dataset['time']">15</button> <button class="workTime__button" data-time="15" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="9">15</button>
<button class="workTime__button" data-time="30" onclick="document.querySelector('#ProductTime').value=this.dataset['time']">30</button> <button class="workTime__button" data-time="30" onclick="document.querySelector('#ProductTime').value=this.dataset['time']" tabindex="10">30</button>
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<button class="workTime__button" id="saveTime">Сохранить</button> <button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button>
</fieldset> </fieldset>
<a onclick="closeDiv();" class="close"></a> <button onclick="closeDiv();" class="close" tabindex="12">&times;</button>
</div> </div>
</div> </div>
</div> </div>
<script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_11_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_11_2017"></script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment