Start Content from bottom of container and push up - html

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>

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>

How to drag and drop same element multiple times into another div box in JavaScript or jQuery?

I have two HTML div boxes. Let's say box A and box B. I want to drag and drop box A multiple times into box B. If I drop box A outside of box B then box A will revert back to it's original position. After I dropped the box A (clone) into box B I want to move box A (clone) into any position in box B. For now I did the codes to do that.
Now what I want is after I dropped box A into Box B, then if I drag and drop box A (clone) outside of box B, then box A (clone) need to hide or revert into it's original position (box A parent position).
HTML Codes
<div id="boxB"></div>
<br>
<div class="boxA">BOX A</div>
CSS Codes
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 40px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
JavaScript + jQuery Codes
$(document).ready(function()
{
var x;
$(".boxA").draggable(
{
helper: "clone",
cursor: "move",
revert: true
});
$("#boxB").droppable(
{
accept: ".boxA",
drop: function(event, ui)
{
x = ui.helper.clone();
ui.helper.remove();
x.appendTo('#boxB');
$(x).draggable();
}
});
});
You can see demo : https://jsfiddle.net/zajjith/3kedjgb0/10/
If I drag and drop box A (clone) outside from box B then that clone box A need to revert back to it's original parent box A position or hide or delete.
I hope you understand what I want. Please check my codes and help me.
Refer to the Example at https://jqueryui.com/droppable/#revert
Using your code, you can do the following.
$(function() {
function getBounds(el) {
var p = $(el).position();
p.right = p.left + $(el).width();
p.bottom = p.top + $(el).height();
return p;
}
function isOver(a, b) {
var ap;
if (typeof a == "object") {
ap = a;
} else {
ap = getBounds(a);
}
var bp = getBounds(b);
return (ap.left > bp.left && ap.right < bp.right) && (ap.top > bp.top && ap.bottom < bp.bottom);
}
$(".boxA").draggable({
helper: "clone",
cursor: "move",
revert: "invalid"
});
$("#boxB").droppable({
accept: ".boxA",
drop: function(event, ui) {
var cl = ui.helper.clone();
cl.appendTo(this).draggable({
appendTo: "body",
stop: function(e, ui) {
if (isOver($.extend({}, ui.position, {
right: ui.position.left + ui.helper.width(),
bottom: ui.position.top + ui.helper.height()
}), $("#boxB")) == false) {
var a = getBounds($("body > .boxA"));
ui.helper.animate({
top: a.top,
left: a.left
}, function() {
ui.helper.remove();
});
} else {
console.log("Drop Inside");
}
}
});
ui.helper.remove();
}
});
});
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 50px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="boxB"></div>
<br />
<div class="boxA">BOX A</div>

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>

RTL - Why the border-right is not changing

I'm trying right to left direction in my HTML as it will be useful for languages like arabic,hebrew
The problem which i face is border-right is not changing it's retained in the same place when shifted to RTL. According to my understanding i thought border-right will be changed as border-left when i switch to RTL mode.
What does RTL property really does?. It just shifts only the content.
If so i can do the workaround by changing the border-right to left in case of RTL. But before doing that i just to want understand what the RTL really does. Please throw some light on it
var rtl = document.getElementById('RTL');
var content = document.getElementById('content');
var currentState;
rtl.onclick = implementRTL;
function implementRTL() {
currentState = content.getAttribute('dir');
if (currentState == 'ltr') {
content.setAttribute('dir', 'rtl');
} else {
content.setAttribute('dir', 'ltr');
}
}
div {
border: 10px solid #000;
border-right: 10px solid red
}
<div id="content" dir="ltr">
Hi Here is the content
</div>
<button id="RTL">
RTL SWITCH
</button>
Check the code below which i tried
border-inline-end
This property sets the right border when the text is LTR and the left border in case of RTL. Similarly, there is border-inline-start for the border on the other side, and border-block-start and border-block-end for the top and bottom borders. They apply correctly to vertical text as well.
var rtl = document.getElementById('RTL');
var content = document.getElementById('content');
var currentState;
rtl.onclick = implementRTL;
function implementRTL() {
currentState = content.getAttribute('dir');
if (currentState == 'ltr') {
content.setAttribute('dir', 'rtl');
} else {
content.setAttribute('dir', 'ltr');
}
}
div {
border: 10px solid #000;
/* border-right: 10px solid red; */ /* old */
border-inline-end: 10px solid red; /* new */
}
<div id="content" dir="ltr">
Hi Here is the content
</div>
<button id="RTL">
RTL SWITCH
</button>
dir="ltr" sets the direction of content flow within a block-level element. This applies to text, inline, and inline-block elements. It also sets the default alignment of text and the direction that table cells flow within a table row.
You can use direction: rtl; in CSS and do something like that :
.rtl {
direction: rtl;
}
.element {
border-right: 1px solid red;
}
.rtl .element {
border-right: none;
border-left: 1px solid red;
}
or
.element {
border-right: 1px solid red;
}
#content:dir(rtl) .element {
border-right: none;
border-left: 1px solid red;
}
When the "dir" attribute of content reflects a value of either ltr or rtl, what gets effected is the direction in which text displays. Altering the border-color of an element generally requires a manual solution. Here is one way to accomplish this feat:
HTML:
<div id="content" dir="ltr">
Hi! Here is the content
</div>
<button id="RL">
RL SWITCH
</button>
CSS:
div,.divltr {
border: 10px solid #000;
border-right: 10px solid red;
}
.divrtl {
border: 10px solid #000;
border-left: 10px solid red;
}
JAVASCRIPT:
var d = document;
d.g = d.getElementById;
var rl = d.g('RL');
var c = d.g('content');
rl.addEventListener('click',function(){
toggleWhichWay();
});
function setTextBorder(whichway) {
c.setAttribute('dir', whichway);
c.className = "div" + whichway;
}
function getCurrState() {
return c.getAttribute('dir');
}
function toggleWhichWay() {
(getCurrState() == 'ltr')? setTextBorder('rtl') :setTextBorder('ltr');
}
see demo.
var toggleButton = document.querySelector('#rtl');
var targetEle = document.querySelector('#content');
function toggleTextDir(ele) {
var dir = ele.attributes.dir.value;
ele.attributes.dir.value = dir === 'rtl' ? 'ltr' : 'rtl';
}
toggleButton.addEventListener('click', function() {
toggleTextDir(targetEle);
});

Nested ng-click's in IE9

I need to have a ng-click-event nested into another ng-click-event.
This doesn't seem to be a problem in the Chrome client I am able to use here at work, but the standard browser is IE9.
The problem is that clicking on the inner control does not trigger the function corresponding to the inner control, but rather the function of the parent control.
The code looks a little like this:
angular.module('App', [])
.controller('Controller', function() {
var self = this;
self.outer_function = function($event) {
alert('Outer function called');
}
self.inner_function = function($event) {
$event.stopPropagation();
alert('Inner function called');
}
});
.outer {
border: 1px solid black;
padding: 10px;
display: inline-block;
}
.inner {
margin: 0 10px;
padding: 5px;
border: 1px solid red;
display: inline-block;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App">
<div ng-controller="Controller as ctrl">
<button class="outer" data-ng-click="ctrl.outer_function($event)">
This is the div
<div class="inner" data-ng-click="ctrl.inner_function($event)">
Inner div
</div>
</button>
</div>
</div>
Is there anything I am forgetting? Or a workaround to make this work in IE9?
Thanks in advance!