How to call a remote navigation menu in html? - html

everytime I make a new tab in my nav menu, I need to edit all my html files.
How do I make a remote file with all the nav items, that I then call to show up?

Simple: make your navigation into a separate HTML file and use an iframe to call it.
Another way is to make it one whole HTML file and use the following:
var d = {
e: function(id){
return(document.getElementById(id) || "err:404");
},
v: function(id){
return(document.getElementById(id).value || "err:404");
}
};
var System = {
tabs: {
init: function(){
try{
var tabs = d.e("tabs").querySelectorAll("tab");
for(var i = 0; i < tabs.length; i++){
var e = tabs[i];
e.onclick = function(){
System.tabs.activate(this);
};
}
System.tabs.activate(tabs[0]);
}catch(err){
alert(err.stack);
}
},
activate: function(name){
try{
var tabs = d.e("tabs").querySelectorAll("tab");
for(var i = 0; i < tabs.length; i++){
tabs[i].setAttribute("active","false");
}
name.setAttribute("active","true");
var contents = d.e("content").querySelectorAll("pane");
for(var i = 0; i < contents.length; i++){
contents[i].style.display = "none";
}
contents[Array.from(tabs).indexOf(name)].style.display = "block";
}catch(err){
alert(err.stack);
}
}
}
};
window.onload = function(){
System.tabs.init();
};
tab{
display: inline-block;
background: #000000;
color: #888888;
height: 20px;
border-right: 1px solid #444444;
border-left: 1px solid #444444;
border-bottom: 1px solid #222222;
}
tab[active="false"]:hover{
background: #000000;
color: #ffffff;
}
tab[active="true"]{
background: #080808;
color: #ffffff;
border-bottom: 1px solid #000000;
}
tab[active="true"]:hover{
background: #181818;
color: #ffffff;
}
<div id="tabs">
<tab>Tab name</tab><tab>Another tab name</tab>
</div>
<div id="content">
<pane>
<p>Hi there! Welcome to some tab program I made! Please click the tab labeled <code>Another tab name</code> to test out the feature.</p>
</pane>
<pane>
<p>The best part is: no need for element IDs or JQuery or any of that difficult stuff! Feel free to click as many times as you want to see how perfect the tabs work.</p>
</pane>
</div>
I realized that the first option might not work with the current knowledge I know. It is still possible though. Meanwhile the second is obviously gonna work very good even though all I know is that it can work in Chrome, but I can't test it in other browsers because this is a school Chromebook that I am on and my dad is refusing to repair mine and my brother's shared PC.

Related

CSS-Add round status button on top of another

I am new to css. How can I add a status button which changes color depending on chat availability on top of another button?
You can use the position property.
See an example code here.
Some resources:
https://www.w3schools.com/css/css_positioning.asp
https://developer.mozilla.org/en-US/docs/Web/CSS/position
From the picture i can tell you don't have to use 2 html elements on top of each other, but you can use css properties like border and background-color to achieve exactly as the button in your picture.
I posted how in the code below with even a little bit of javascript to toogle the button status (not needed for styling, so if you don't know any javascript yet, you can skip that part).
let isOpen = false;
const btn = document.querySelector("#btn");
const dot = document.querySelector(".dot");
const txt = document.querySelector("#text");
btn.addEventListener("click", () => {
if (isOpen) {
dot.style.backgroundColor = "red";
txt.innerHTML = "The chat is now closed";
} else {
dot.style.backgroundColor = "green";
txt.innerHTML = "The chat is now open";
}
isOpen = !isOpen;
});
.dot {
height: 25px;
width: 25px;
background-color: red;
border-radius: 50%;
display: inline-block;
border: 5px solid gray;
}
#wrapper {
border: 1px solid black;
text-align: center;
padding: 10px;
}
#btn {
margin-top: 10px;
}
<div id="wrapper">
<span class="dot"></span>
<p id="text">The chat is now closed</p>
</div>
<button id="btn">Toogle</button>

Sidebar Functionality

I have continued to develop a sidebar capability within my google sheet.
I have am looking for some assistance in creating a flow within the sidebar and using links or buttons to create some output messages.
Problem 1) - I have created a sidebar with forward and back arrows which I want to link other html files to when they are clicked within the sidebar, therefore creating a flow or dialog that can be moved back or forth in the same sequence. i.e.. I click next and the function openTheSidebar2() runs
I have have a search dropdown feature which in the code below gives Primary risk categories.
Problem 2) - I would like these to have the ability to provide a simple paragraph (explanation of each category) when they are selected. Would I need to create a different html file for each category? I'm hoping I can add the each message for each category in the same html file.
Is hyperlinks the wrong way to go about this altogether?
Any help is much appreciated
code.gs
function onOpen() {
menu();
}
function menu() {
SpreadsheetApp.getUi().createMenu('Risk Menu')
.addItem('Generate Risk Waiver', 'createNewCase')
.addSubMenu(SpreadsheetApp.getUi().createMenu('Risk Help')
.addItem('Risk Guidance', 'openTheSidebar')
.addItem('Risk Title', 'openTheSidebar2'))
.addToUi();
}
function openTheSidebar() {
var userInterface=HtmlService.createTemplateFromFile('example3').evaluate()
.setTitle('Risk Rating');
SpreadsheetApp.getUi().showSidebar(userInterface);
}
function openTheSidebar2() {
var userInterface2=HtmlService.createTemplateFromFile('example4').evaluate()
.setTitle('Primary Risk Category');
SpreadsheetApp.getUi().showSidebar(userInterface2);
}
function openTheSidebar3() {
var userInterface3=HtmlService.createTemplateFromFile('example').evaluate()
.setTitle('Cause');
SpreadsheetApp.getUi().showSidebar(userInterface3);
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function getRowColumn() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveCell();
var rObj={row:rg.getColumn() ,column:rg.getRow()};
return rObj;
}
function getCellA1() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveCell();
var rObj={A1:rg.getA1Notation()};
return rObj;
}
function onCheckOpenSideBar(e) {
if(e.range.getSheet().getName()!='Option 1')return;
if(e.range.rowStart==2 && e.range.columnStart==24) {
if(e.value=='TRUE') {
openTheSidebar();
e.range.getSheet().getRange(e.range.rowStart,e.range.columnStart).setValue("FALSE");
}
}
if(e.range.getSheet().getName()!='Option 1')return;
if(e.range.rowStart==2 && e.range.columnStart==8) {
if(e.value=='TRUE') {
openTheSidebar2();
e.range.getSheet().getRange(e.range.rowStart,e.range.columnStart).setValue("FALSE");
}
}
if(e.range.getSheet().getName()!='Option 1')return;
if(e.range.rowStart==2 && e.range.columnStart==1) {
if(e.value=='TRUE') {
openTheSidebar3();
e.range.getSheet().getRange(e.range.rowStart,e.range.columnStart).setValue("FALSE");
}
}}
function createOnEditTrigger() {
ScriptApp.newTrigger('onCheckOpenSideBar').forSpreadsheet(SpreadsheetApp.getActive()).onEdit().create();
}
example4.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #3e8e41;
}
#myInput {
border-box: box-sizing;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: none;
border-bottom: 1px solid #ddd;
}
#myInput:focus {outline: 3px solid #ddd;}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
border: 1px solid #ddd;
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd;}
.show {display: block;}
a {
text-decoration: none;
display: inline-block;
padding: 8px 16px;
}
a:hover {
background-color: #ddd;
color: black;
}
.previous {
background-color: #f1f1f1;
color: black;
}
.next {
background-color: #4CAF50;
color: white;
}
.round {
border-radius: 50%;
}
</style>
</head>
<body>
<p>Click on the button to open the dropdown menu, and use the input field to search for a specific dropdown link.</p>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Categories</button>
‹
&#8250
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
IT Security & Vulnerability
Information Security - Data Only
Technical Debt or Decommission
Availability (SLA)
Service Continuity & Resilience
Capacity & Performance
Licencing & Asset Management, Contracts, Maintenance,
Legal & Regulatory Compliance
Supplier & Vendor Management
Shadow IT
Resource
Knowledge / Skills / Tooling)
Procedure & Process
Service Ownership
Project
Environmental (includes facilities)
Architecture and Strategic
</div>
</div>
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
txtValue = a[i].textContent || a[i].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
a[i].style.display = "";
} else {
a[i].style.display = "none";
}
}
}
</script>
</body>
</html>
I think I understand your question, but if I've got it wrong, just let me know. Your question is somewhat broad and there are many solutions to what you want to do. Here are a couple of ways I might start to approach it.
Method 1: Serve it all at once; show and hide as needed
As shown here, use a helper function include to break up your HTML files for development and then pull them all together when you run the app.
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
Content snippet in its own .html file, and give the outermost HTML element a distinct id.
<section id="IT_Security_And_Vulnerability" class="hidden">
<h1>IT Security & Vulnerability</h1>
<p> ...
</p>
</section>
Print all those html files into your main html file you return to the user.
Main html file snippets:
<style>
.hidden {
display: none;
}
</style>
<?= include("#IT_Security_And_Vulnerability") ?>
<?= include("#Information_Security_Data_Only") ?>
<!-- etc -->
<script>
const body = document.querySelector("body"); // this just grabs the sidebar body
body.addEventListener("click", handleClick);
function handleClick(clickEvent) {
if (clickEvent.target.tagname != "A") { // this listener only for clicking links
return;
}
clickEvent.target.preventDefault(); // you may or may not want/need this to prevent browser from trying to actually navigate with your <a> tag
const id = clickEvent.target.getAttribute("href");
const sections = document.querySelectorAll("section");
for (let i = 0, l = sections.length; i < l; ++i) { // hide everyone
sections[i].classList.add("hidden");
}
document.querySelector(id).classList.remove("hidden"); // show the selected one
}
</script>
Method 2: Use google.script.run to fetch content as needed
Still using the include function on the server, this serves up the content on demand.
...
<section class="contentContainer">
<!-- populated by js -->
</section>
...
<script>
const body = document.querySelector("body"); // this just grabs the sidebar body
body.addEventListener("click", handleClick);
function refresh(html) {
const contentContainer = document.querySelector(".contentContainer");
contentContainer.innerHTML = html;
}
function handleClick(clickEvent) {
if (clickEvent.target.tagname != "A") {
return;
}
clickEvent.target.preventDefault(); // you may or may not want/need this.
const reference = clickEvent.target.getAttribute("href");
google.script.run.withSuccessHandler(refresh).include(reference);
}
</script>

Browse button that will display image file from a local directory folder in html

Hi I wanted to know if its possible to create a button in html that functions like a "Browse" button like when clicked it will show the computer directory such as the Local Drive, Documents etc.
What I wanted to do is use this "Browse" button to set a Folder path that has Images (.png/.jpeg) then once directory folder has been selected the image file name should show up in a list form.
*Note: The machine is connected on a LAN network everything is shared and with
out any restriction.
Sample
Path:
C:\Documents\TargetFolder (this is what will be browsed using the "Browse" button the path location may change could be from a different location within the same machine or different computer over the same network that is why a "Browse" button is needed)
Output:
From the Source(TargetFolder) lets say with 20 image file a list should show up with the image file name, path properties(created date and time )and the actual image pulled up. Switches as well base on what was selected on the list
Is this possible?
browse button window
webpage looks like this
What you want actually is a file manager (file gallery to be more precise) in web browser.
there is no such thing in that would help you get that without writing hundreds of lines of code.
This link might help you https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
and also follow the below code
var input = document.querySelector('input');
var preview = document.querySelector('.preview');
input.style.opacity = 0;input.addEventListener('change', updateImageDisplay);function updateImageDisplay() {
while(preview.firstChild) {
preview.removeChild(preview.firstChild);
}
var curFiles = input.files;
if(curFiles.length === 0) {
var para = document.createElement('p');
para.textContent = 'No files currently selected for upload';
preview.appendChild(para);
} else {
var list = document.createElement('ol');
preview.appendChild(list);
for(var i = 0; i < curFiles.length; i++) {
var listItem = document.createElement('li');
var para = document.createElement('p');
if(validFileType(curFiles[i])) {
para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i].size) + '.';
var image = document.createElement('img');
image.src = window.URL.createObjectURL(curFiles[i]);
listItem.appendChild(image);
listItem.appendChild(para);
} else {
para.textContent = 'File name ' + curFiles[i].name + ': Not a valid file type. Update your selection.';
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}var fileTypes = [
'image/jpeg',
'image/pjpeg',
'image/png'
]
function validFileType(file) {
for(var i = 0; i < fileTypes.length; i++) {
if(file.type === fileTypes[i]) {
return true;
}
}
return false;
}function returnFileSize(number) {
if(number < 1024) {
return number + 'bytes';
} else if(number >= 1024 && number < 1048576) {
return (number/1024).toFixed(1) + 'KB';
} else if(number >= 1048576) {
return (number/1048576).toFixed(1) + 'MB';
}
}
html {
font-family: sans-serif;
}
form {
width: 600px;
background: #ccc;
margin: 0 auto;
padding: 20px;
border: 1px solid black;
}
form ol {
padding-left: 0;
}
form li, div > p {
background: #eee;
display: flex;
justify-content: space-between;
margin-bottom: 10px;
list-style-type: none;
border: 1px solid black;
}
form img {
height: 64px;
order: 1;
}
form p {
line-height: 32px;
padding-left: 10px;
}
form label, form button {
background-color: #7F9CCB;
padding: 5px 10px;
border-radius: 5px;
border: 1px ridge black;
font-size: 0.8rem;
height: auto;
}
form label:hover, form button:hover {
background-color: #2D5BA3;
color: white;
}
form label:active, form button:active {
background-color: #0D3F8F;
color: white;
}
<form method="post" enctype="multipart/form-data">
<div>
<label for="image_uploads">Choose images to upload (PNG, JPG)</label>
<input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
</div>
<div class="preview">
<p>No files currently selected for upload</p>
</div>
<div>
<button>Submit</button>
</div>
</form>
Not exactly what you asked for, but (if it works for your use-case), the user could select multiple files from the same directory using the browse button.
There is a lovely example on MDN
https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#example_showing_thumbnails_of_user-selected_images
<input type="file" id="input" multiple>
const inputElement = document.getElementById("input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
}
function handleFiles(files) {
for (let i = 0; i < files.length; i++) {
const file = files[i];
if (!file.type.startsWith('image/')){ continue }
const img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Assuming that "preview" is the div output where the content will be displayed.
const reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}

How to disable my element auto-scroll briefly

I used the answer to this question to auto-scroll a combat log for my HTML5 game to the bottom:
How to auto-scroll to end of div when data is added?
If I want to briefly disable this while a person clicks to scroll up and view the log, how would I do so?
The Code I'm using is:
//autoscroll combat log
window.setInterval(function() {
var elem = document.getElementById('log');
elem.scrollTop = elem.scrollHeight;
}, 500);
Best regards,
Cobwebs
Edit: the code above is connected to a simple span in a div:
<div>
<span id='log'></span>
</div>
Stylized to have a scrollbar:
span#log {
display: block;
font-family: courier, sans;
margin: auto;
border:1px solid black;
width:600px;
height:200px;
overflow:auto;
background-color:black;
color: lime;
text-align: left;
}
setInterval() returns an ID, with that ID you can use clearInterval() to stop it
var intervalID = window.setInterval(function() {
var elem = document.getElementById('log');
elem.scrollTop = elem.scrollHeight;
}, 500);
and then this
window.clearInterval(intervalID);
small DEMO

Start Content from bottom of container and push up

So what I'm trying to accomplish seems like easy CSS etc. Im changing a messaging system and what the conversations to start at the bottom sorta like Facebook or text message where it has one person on the left and the other on the right.
How do I get the divs to go up as new content is added via ajax? I saw this similar question but didn't quite understand what he mean focus on the LI. An example would be great.
Something like this perhaps?
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function prependChild(parent, element)
{
if (parent.childNodes)
parent.insertBefore(element, parent.childNodes[0]);
else
parent.appendChild(element)
}
window.addEventListener('load', mInit, false);
function mInit()
{
byId('btnAddNew').addEventListener('click', onAddBtnClicked, false);
}
function onAddBtnClicked()
{
var txtInputElem = byId('newMsgTxtInput');
var msgTxt = txtInputElem.value;
var li = newEl('li');
li.appendChild( newTxt( msgTxt ) );
var ulTgt = byId('msgTarget');
var existingLiItems = ulTgt.querySelectorAll('li');
var numItemsExisting = existingLiItems.length;
if (numItemsExisting%2 != 0)
li.className = 'even';
else
li.className = 'odd';
prependChild(ulTgt, li);
}
</script>
<style>
.controls
{
display: inline-block;
padding: 8px;
margin: 8px;
border: solid 1px #555;
border-radius: 4px;
color: #777;
background-color: #ddd;
}
#msgTarget
{
width: 275px;
border: solid 1px #555;
margin: 8px;
border-radius: 4px;
}
/*
Doesn't work 'properly' - since we add items at the top, rather than the bottom
The first item added will be 'even', then the second item gets added and now it's the first child 'even'
so, the item added first is now an 'odd' child. A better way may be to count the number of existing li
items the ul contains, before assigning the new li elements a class of even or odd that will enable css
styling.
#msgTarget li:nth-child(odd)
{
background-color: #CCC;
}
#msgTarget li:nth-child(even)
{
background-color: #5C5;
}
*/
.odd
{
background-color: #CCC;
}
.even
{
background-color: #5C5;
}
</style>
</head>
<body>
<div class='dlg'>
<div class='controls'>
<input id='newMsgTxtInput'/><button id='btnAddNew'>Add message</button>
</div>
<ul id='msgTarget'></ul>
</div>
</body>
</html>