class BlueWeather { constructor(profileObjectParent) { // cunstruct xmlhttp this.xhttp = new XMLHttpRequest(); //this.host = "https://weather.itsblue.de" this.host = window.location.href.substring(0, window.location.href.lastIndexOf("/")); this.profileObjectParent = profileObjectParent this.log("init done", 2) this.session = { loggedIn: false, token: "", user: { realName: "Real Name", username: "username" } } this.restoreSession() } // ---------------------- // - session management - // ---------------------- restoreSession() { var thisObject = this if (this.getCookie("session") !== "" && this.getCookie("session") !== undefined && this.getCookie("session") !== "undefined") { // old session found console.log("old session found: " + this.getCookie("session"), 3) // check if the session is still valid this.checkSession(this.getCookie("session"), function (sessionIsValid) { if (sessionIsValid) { thisObject.session.loggedIn = true thisObject.session.token = thisObject.getCookie("session") } thisObject.loadProfileObject(thisObject.profileObjectParent) }) } else { this.loadProfileObject(this.profileObjectParent) } } login(async, username, password, processingFunction) { var xhttp = new XMLHttpRequest(); var thisObject = this if (async) { xhttp.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { thisObject.log("login response was: " + this.responseText, 3) var ret = JSON.parse(this.responseText) if (ret && ret['header'] === 200) { thisObject.session.token = ret["body"] document.cookie = "session=" + ret["body"] + ";" thisObject.session.loggedIn = true processingFunction(true) return } else { thisObject.endSession() } } processingFunction(false) } } } var request = JSON.stringify({ header: 1000, body: { username: username, password: password } }) var url = this.host + "/api/json.php?command=" + request this.log("starting login request; URL is: " + url, 3) xhttp.open("GET", url, async) xhttp.send() } logout() { var xhttp = new XMLHttpRequest(); var thisObject = this xhttp.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { thisObject.log("logout response was: " + this.responseText, 3) document.cookie = "session=;" location.reload() } } } var request = JSON.stringify({ header: 1002, body: this.session.token }) var url = this.host + "/api/json.php?command=" + request this.log("starting logout request; URL is: " + url, 3) xhttp.open("GET", url, true) xhttp.send() } checkSession(token, processingFunction) { var xhttp = new XMLHttpRequest(); var thisObject = this xhttp.onreadystatechange = function () { if (this.readyState === 4) { if (this.status === 200) { thisObject.log("login response was: " + this.responseText, 3) var ret = JSON.parse(this.responseText) if (ret && ret['header'] === 200) { thisObject.session.user.username = ret["data"]["username"] thisObject.session.user.realName = ret["data"]["realname"] thisObject.session.user.email = ret["data"]["email"] thisObject.session.user.emailHash = ret["data"]["emailHash"] processingFunction(true) return } else { thisObject.endSession() } } processingFunction(false) } } var request = JSON.stringify({ header: 1001, body: token }) var url = this.host + "/api/json.php?command=" + request this.log("starting session check request; URL is: " + url, 3) xhttp.open("GET", url, true) xhttp.send() } endSession() { document.cookie = "session=;" if (this.session.loggedIn) { // if the user was logged in before location.reload() } } // -------------------- // - getter functions - // -------------------- getLocations(async, processingFunction, errorFunction) { this.xhttp.abort() var thisObject = this if (async) { this.xhttp.onreadystatechange = function () { if (this.readyState === 4) { // Typical action to be performed when the document is ready: if (this.status === 200) { thisObject.log("getting sensors response was: " + this.responseText, 3) var ret = JSON.parse(this.responseText) if (ret) { processingFunction(ret); return } } if (errorFunction !== null) { errorFunction(this.status, this.text) } } }; } var url = this.host + "/api/json.php" this.log("starting location request; URL is: " + url, 3) this.xhttp.open("GET", url, async) this.xhttp.send() } getLocationData(locId, range = { from: "", to: "" }, maxVals = 0, async, processingFunction, errorFunction) { this.xhttp.abort() var thisObject = this if (async) { this.xhttp.onreadystatechange = function () { if (this.readyState === 4) { // Typical action to be performed when the document is ready: if (this.status === 200) { thisObject.log("getting sensors response was: " + this.responseText, 3) var ret = JSON.parse(this.responseText) if (ret) { processingFunction(ret); return } } if (errorFunction !== null) { errorFunction(this.status, this.text) } } }; } var url = this.host + "/api/json.php?locId=" + locId + "&range[from]=" + range.from + "&range[to]=" + range.to + "&maxVals[mode]=" + maxVals.mode + "&maxVals[count]=" + maxVals.count this.log("starting location request; URL is: " + url, 3) this.xhttp.open("GET", url, async) this.xhttp.send() } // ---------------------- // - template functions - // ---------------------- loadProfileObject(parent) { parent = this.profileObjectParent if (!parent) { this.log("error: no profile object parent", 3) return false } parent = document.getElementById(parent) var thisObject = this var profileObject = document.createElement("li") parent.appendChild(profileObject) profileObject.classList.add("nav-item") if (!this.session.loggedIn) { this.log("not logged in", 3) profileObject.classList.add("text-nowrap") // create login button var loginButton = document.createElement('button') profileObject.appendChild(loginButton) loginButton.type = "button" loginButton.setAttribute("data-toggle", "modal") loginButton.setAttribute("data-target", "#loginModal") loginButton.classList.add("btn", "btn-outline-light") loginButton.innerHTML = "Login" // ------------ // create modal var loginModal = document.createElement('div') loginModal.id = "loginModal" loginModal.setAttribute("tabindex", "-1") loginModal.setAttribute("role", "dialog") loginModal.setAttribute("aria-labelledby", "exampleModalLabel") loginModal.setAttribute("aria-hidden", "true") loginModal.classList.add("modal", "fade") // create login form var loginDiv = document.createElement("div") loginModal.appendChild(loginDiv) loginDiv.classList.add("modal-dialog", "modal-login") loginDiv.setAttribute("role", "document") // - modal content var modalContent = document.createElement("div") loginDiv.appendChild(modalContent) modalContent.classList.add("modal-content") // -- modal header var modalHeader = document.createElement("div") modalContent.appendChild(modalHeader) modalHeader.classList.add("modal-header") // --- close button var modalCloseButton = document.createElement("button") modalHeader.appendChild(modalCloseButton) modalCloseButton.setAttribute("type", "button") modalCloseButton.setAttribute("data-dismiss", "modal") modalCloseButton.setAttribute("aria-label", "Close") modalCloseButton.classList.add("close") modalCloseButton.innerHTML = '' // -- modal body var modalBody = document.createElement("div") modalContent.appendChild(modalBody) modalBody.classList.add("modal-body", "text-center") // --- login form var loginForm = document.createElement("form") modalBody.appendChild(loginForm) loginForm.classList.add("form-signin") // ---- login form fieldset var fieldset = document.createElement("fieldset") loginForm.appendChild(fieldset) // ----- blueweather icon var loginFormIcon = document.createElement("img") fieldset.appendChild(loginFormIcon) loginFormIcon.width = "72" loginFormIcon.height = "72" loginFormIcon.src = "img/icon.png" loginFormIcon.alt = "" loginFormIcon.classList.add("mb-4") // ----- 'Please sign in' text var loginFormHeadline = document.createElement("h1") fieldset.append(loginFormHeadline) loginFormHeadline.classList.add("h3", "mb-3", "font-weight-normal") loginFormHeadline.innerHTML = "Please sign in" // ----- login failed alert var alert = document.createElement("div") fieldset.append(alert) alert.id = "loginFormLoginFailedAlert" alert.appear = function () { alert.innerHTML = '' } // ----- username input var usernameInputGroup = document.createElement("div") fieldset.appendChild(usernameInputGroup) usernameInputGroup.classList.add("form-group", "input-group") usernameInputGroup.innerHTML = '
' // ----- password input var passwordInputGroup = document.createElement("div") fieldset.appendChild(passwordInputGroup) passwordInputGroup.classList.add("form-group", "input-group") passwordInputGroup.innerHTML = '
' // ----- 'remember me' checkbox var rememberCheckboxContainer = document.createElement("div") rememberCheckboxContainer.classList.add("checkbox", "mb-3") rememberCheckboxContainer.innerHTML = '' // ----- 'sign in' button var signInButton = document.createElement("button") modalBody.appendChild(signInButton) signInButton.id = "loginFormSignInButton" signInButton.type = "submit" signInButton.classList.add("btn", "btn-lg", "btn-primary", "btn-block") signInButton.innerHTML = "Sign in" signInButton.setLoading = function () { signInButton.disabled = true signInButton.innerHTML = ' Signing in...' } signInButton.setNormal = function () { signInButton.disabled = false signInButton.innerHTML = 'Sign in' } signInButton.onclick = function () { signInButton.setLoading() var username = document.getElementById("loginFormUsernameInput").value var password = document.getElementById("loginFormPasswordInput").value thisObject.login(true, username, password, function (loginSuccess) { if (!loginSuccess) { alert.appear() signInButton.setNormal() } else { location.reload() } }) } // ---------- parent.appendChild(loginModal) } else { this.log("logged in", 3) profileObject.classList.add("dropdown") // create profile picture button var profileButton = document.createElement("a") profileObject.appendChild(profileButton) profileButton.id = "userDropdown" profileButton.style = "padding: 0;" profileButton.href = "#" profileButton.setAttribute("role", "button") profileButton.classList.add("nav-link", "dropdown-toggle") profileButton.setAttribute("data-toggle", "dropdown") profileButton.setAttribute("aria-haspopup", "true") profileButton.setAttribute("aria-expanded", "false") // create profile image inside button var profileImage = document.createElement("img") profileButton.appendChild(profileImage) profileImage.height = "30" profileImage.src = "https://www.gravatar.com/avatar/"+this.session.user.emailHash+".jpg?d=identicon" profileImage.classList.add("img-profile", "rounded-circle") // create dropdown menu var profileDropdown = document.createElement("div") profileObject.appendChild(profileDropdown) profileDropdown.classList.add("dropdown-menu", "dropdown-menu-right") profileDropdown.setAttribute("aria-labelledby", "userDropdown") // fill the dropdown menu function createDropdownMenuElement(icon, text, onclick = null) { // create element var elem = document.createElement("a") elem.classList.add("dropdown-item") elem.href = "#" elem.onclick = onclick // create icon var iconSpan = document.createElement("span") elem.appendChild(iconSpan) iconSpan.setAttribute("data-feather", icon) // create text var text = document.createTextNode(text) elem.appendChild(text) return elem } function createDropdownSeparator() { var sep = document.createElement("div") sep.classList.add("dropdown-divider") return sep } var header = document.createElement("div") header.classList.add("dropdown-item") header.innerHTML = "
" + this.session.user.realName + "
@" + this.session.user.username profileDropdown.appendChild(header) profileDropdown.appendChild(createDropdownSeparator()) profileDropdown.appendChild(createDropdownMenuElement("settings", " Settings")) profileDropdown.appendChild(createDropdownSeparator()) profileDropdown.appendChild(createDropdownMenuElement("log-out", " Log out", function () { thisObject.logout() })) } feather.replace() } // -------------------- // - helper functions - // -------------------- getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); if (parts.length == 2) return parts.pop().split(";").shift(); } findGetParameter(parameterName) { var result = null, tmp = []; location.search .substr(1) .split("&") .forEach(function (item) { tmp = item.split("="); if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]); }); return result; } log(text, level) { // levels: // 0: error // 1: warning // 2: info // 3: debug var preString = "[BlueWeather]" switch (level) { case 0: preString += "[error] " console.error(preString + text) break case 1: preString += "[warining] " console.warn(preString + text) break case 2: preString += "[info] " console.log(preString + text) break case 3: preString += "[debug] " console.debug(preString + text) } } }