As you can see, 3 divs are created using JavaScript when their respective buttons are clicked. I pass their values and then use those to create the content. I am not sure if this is the best way... but anyway.
The problem is that the divs keep appending. I only want to show one div at a time, and I also want to disable the active div's button. I've seen that you can use something like document.querySelector('button[onclick]').disabled = true;, but I am unsure of how to make it dynamically work because it would have to be set to false once any of the other buttons are clicked.
Here is my JavaScript that is responsible for creating the content:
function showDiv(name) {
var selectedButton = name.value;
var div = document.createElement('div');
div.id = 'myDiv';
document.body.appendChild(div);
if (selectedButton === 'home') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
} else if (selectedButton === 'about') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
} else if (selectedButton === 'contact') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
}
}
My JSFiddle: http://jsfiddle.net/wwen39o9/
I've updated your fiddle: http://jsfiddle.net/wwen39o9/3/
In short, add one div to the html:
<div id="myDiv"></div>
Give buttons a class navbutton:
Javascript:
function showDiv(me) {
$('.navbutton').prop('disabled', false);
$(me).prop('disabled', true);
$('#myDiv').html('Hi, this is a test for my ' + $(me).val() + ' div.');
}
Pure JS version without jQuery:
function showDiv(me) {
var div = document.getElementById('myDiv');
var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].className == 'navbutton')
buttons[i].disabled = false;
}
me.disabled = true;
div.innerHTML = 'Test for ' + me.value;
}
A couple of ways to set an active button in a group of buttons:
If they are confined to a wrapper:
function setActive(selectedButton){
var parent = selectedButton.parentNode;
var children = parent.getElementsByTagName('button');
var child_ct = children.length - 1;
while (child_ct) {
children[child_ct].disabled = false;
child_ct--;
}
selectedButton.disabled = true;
}
Or by giving all a class like .nav-btn
function setActive(selectedButton) {
var parent = selectedButton.parentNode;
var children = parent.getElementsByClassName('nav-btn');
var child_ct = children.length - 1;
while (child_ct) {
children[child_ct].disabled = false;
child_ct--;
}
selectedButton.disabled = true;
}
A good way to swap out div:
Check if div exists. Replace content if so, create div if not.
function showDiv(content) {
var div = document.getElementById('the-div');
if (div) {
//May be better to remove children, then append content, but...
div.innerHTML = content
} else {
var the_div = document.createElement('div');
the_div.id = 'the-div';
the_div.innerHTML = content;
document.appendChild(the_div);
}
}
So:
function handleClick() {
setActive(this);
if (this.name === 'home') {
showDiv('Information about being home');
}
}
<button onclick="handleClick">
The append method should be call only if we did not found one.
Something like
function showDiv(name) {
var selectedButton = name.value;
var div = document.getElementById('myDiv');
if(!div) {
document.createElement('div');
div.id = 'myDiv';
document.body.appendChild(div);
}
We can check the number of div elements on page
Or why not to do it like following. At the beginning we have an empty div with id="myDiv" and then we are just changing its content with JavaScript. Have a look at JSFiddle example.
HTML
<button value="home" onclick="showDiv(this);">Home</button>
<button value="about" onclick="showDiv(this);">About</button>
<button value="contact" onclick="showDiv(this);">Contact</button>
<!-- create an empty div -->
<div id="myDiv"></div>
JavaScript
function showDiv(name) {
var selectedButton = name.value;
var div = document.getElementById('myDiv');
if (selectedButton === 'home') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
} else if (selectedButton === 'about') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
} else if (selectedButton === 'contact') {
div.innerHTML = 'Hi, this is a test for the ' + selectedButton + ' div.';
}
}
Related
I want to add an event on an element does doesn't exist in the original HTML (created with innerHtml). When i click nothing happens.
const btnRemove = document.getElementById("remove");
btnMow.addEventListener("click", function mow() {
if (sMow === true) {
reqServices.push("Mow Lawn");
service.innerHTML += `
<div class="v1">
<p class="v3-text">Mown Lawn <span id="remove">remove</span></p>
<p class="v3-dollar"><span>$</span>20</p>
</div>`;
sMow = false;
total += 20;
totalC();
}
});
btnRemove.addEventListener("click", function remove() {
alert("HELLO");
});
I want to add a click event on the element with id remove.
Another way to do that is creating the elements instead of use the HTML code and a later search. This maybe useful if you, for example, don't want to add an id to the remove tag
btnMow.addEventListener("click", function mow() {
if (sMow === true) {
reqServices.push("Mow Lawn");
var div = document.createElement("div");
div.className = "v1";
service.appendChild(div);
var p1 = document.createElement("p");
p1.className = "v3-text";
div.appendChild(p1);
var p1Text = document.createTextNode("Mown Lawn ");
p1.appendChild(p1Text);
var p1Span = document.createElement("span");
p1Span.setAttribute("id", "remove");
p1Span.innerText = "remove";
p1Span.addEventListener("click", function remove() {
alert("HELLO");
});
p1.appendChild(p1Span);
var p2 = document.createElement("p");
p2.className = "v3-dollar";
p2.innerHTML = "<span>$</span>20";
div.appendChild(p2);
sMow = false;
total += 20;
totalC();
}
});
As you can see, creating the elements allow you do whatever you want with it. It's longer but you can use a helper function like this:
function appendTag(parent, tagName, className) {
var tag = document.createElement(tagName);
if (className)
tag.className = className;
parent.appendChild(tag);
return tag;
}
And rewrite as:
btnMow.addEventListener("click", function mow() {
if (sMow === true) {
reqServices.push("Mow Lawn");
var div = appendTag(service, "div", "v1");
var p1 = appendTag(div, "p", "v3-text");
p1.appendChild(document.createTextNode("Mown Lawn "));
var p1Span = appendTag(p1, "span");
p1Span.setAttribute("id", "remove");
p1Span.innerText = "remove";
p1Span.addEventListener("click", function remove() {
alert("HELLO");
});
var p2 = appendTag(p1, "p", "v3-dollar");
p2.innerHTML = "<span>$</span>20";
sMow = false;
total += 20;
totalC();
}
});
btnMow.addEventListener("click", function mow() {
if (sMow === true) {
reqServices.push("Mow Lawn");
service.innerHTML += `
<div class="v1">
<p class="v3-text">Mown Lawn <span id="remove">remove</span></p>
<p class="v3-dollar"><span>$</span>20</p>
</div>`;
sMow = false;
total += 20;
totalC();
}
const btnRemove = document.getElementById("remove");
btnRemove.addEventListener("click", function remove() {
alert("HELLO");
});
});
var btnremove = document.getElementById("remove");
write this before starting click event
I have a javascript class (ES6) and I'm trying to assign a function from that class to a button created by the class. This my main class
class tabDrawer {
constructor(bodyID) {
this.bodyID = bodyID;
this.tabArray = [];
this.initialized = false;
}
get getBodyID() {
return this.bodyID;
}
initialize() {
this.body = document.getElementById(this.bodyID);
var baseHTML = "<div id='tabDiv'><div class='tab'></div><div class='tabContentDiv'></div></div>";
this.body.innerHTML = baseHTML;
this.initialized = true;
}
addTab(tab) {
if(this.initialized) {
var tabClass = "tabLinks";
if(this.tabArray.length === 0) {
tabClass += " active";
}
console.log(this.tabArray.length);
this.body.children[0].children[0].innerHTML += "<button class='" + tabClass + "' id='btn" + tab.name + "'>" + tab.tabTitle + "</button>";
this.body.children[0].children[1].innerHTML += "<div style='display: none' id='" + tab.name + "' class='tabContent'>" + tab.content + "</div>"
var tabButton = document.getElementById("btn" + tab.name);
tabButton.addEventListener("click", evt => this.openTab(evt));
this.tabArray[this.tabArray.length] = tab;
}
}
openTab(index) {
var tabByIndex = this.tabArray[index];
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabContent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tabLinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabByIndex.name).style.display = "block";
document.getElementById("btn" + tabByIndex.name).className += " active";
}
}
When a tab gets added (as seen in addTab()) the class creates a button in the tabDrawers body and I want to assign the function openTab(index) which is also in the class. I know I can't just add the event listener with "this.openTab" as it will refer to the button instead of the class.
The line tabButton.addEventListener("click", evt => this.openTab(evt));seems to work but I'm not sure how to pass the index parameter to the function as I want the function to still be available to the end user as well so they can do this: tabs.openTab(0); with "tabs" being an instance of tabDrawer.
Can this be done? If so, how can I do this?
You should use Document.createElement() to create HTML elements (not innerHTML) then you can assign events to those created elements. Simple as this:
var myClickMeFunction = function() {
alert('you clicked myClickMeFunction');
};
var button = document.createElement('button');
button.classList.add('xxx');
button.textContent = 'Click me';
button.addEventListener('click', myClickMeFunction);
document.body.appendChild(button);
.xxx {
background-color: orange;
}
To pass the index, you should use this.tabArray.length instead of evt in your event. The problem is that the length will change when adding another tab, so you need to scope it:
var self = this;
var handler = function (index){
return function(){
self.openTab(index);
}
}
tabButton.addEventListener("click",handler(this.tabArray.length));
This will execute the handler function, to create the event handler using the index from the parameter.
You could do way simpler tough... The only reason you are needing the index is to grab the tab from a tabArray! Why not simply pass the tab directly? This would make it way simpler:
tabButton.addEventListener("click",()=>this.openTab(tab));
I currently have a JavaScript that is looking at a SharePoint list, and pulling back all of the items that meet the criteria in the REST call.
It currently creates DIVs and appends them to a wrapper DIV. The intention of the button is to show/hide the sub-DIVs.
Right now, when I click any of the buttons that are produced, it expands all of the hidden divs. What I'm trying to accomplish is to be able to click each respective button and have its nested div show/hide.
Here is my code:
var listName = "announcement";
var titleField = "Title";
var tipField = "Quote";
var dateFieldFrom = "DateFrom";
var dateFieldTo = "DateTo";
var category = "category";
var noteField = "note";
var query = "/_api/Web/Lists/GetByTitle('" + listName + "')/items?$select=" + titleField + "," + dateFieldTo + "," + dateFieldFrom + "," + category + "," + noteField + "," + tipField;
var today = new Date();
var btnClass = "toggle"
todayString = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate();
//This is the query filter string where we compare the values in the 2 date fields against the current date
query += "&$filter=('" + todayString + "' ge " + dateFieldFrom + " ) and (" + dateFieldTo + " ge '" + todayString + "')";;
var call = $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + query,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call.done(function(data, textStatus, jqXHR) {
var divCount = data.d.results.length;
for (var i = 0; i < divCount; i++) {
var tip = data.d.results[i][tipField]; //this is where it looks at the quote field to determine what quote to place in the current dynamically created DIV
var cat = data.d.results[i][category]; //this is where it looks at the category field to determine what color to style the background of the current dynamically created DIV
var message = data.d.results[i][noteField];
var ID = "NewDiv-" + i
var PID = "P-" + i
var BID = "btn-" + i
// Create Message DIV
var element = document.createElement("div"); //This is the creation of the dynamic DIV
element.id = ID //This is assigning a DIV an ID
element.appendChild(document.createTextNode(tip));
// Create Inner message DIV
var innerDiv = document.createElement("div"); // Create a <div> element//New Code
innerDiv.id = PID
innerDiv.appendChild(document.createTextNode(message));
// Create button to show/hide the div
var btn = document.createElement("BUTTON");
btn.id = BID
btn.appendChild(document.createTextNode("show/hide message below"));
btn.className = btnClass
// Append Inner DIVs
document.getElementById('wrapper').appendChild(element); //This is the parent DIV element that all newly created DIVs get created into
document.getElementById(ID).appendChild(btn); // Append the button to the newly created DIV
document.getElementById(ID).appendChild(innerDiv); //This is the message that appears after the newly created DIVs
if (cat == 'Information') {
document.getElementById(ID).style.backgroundColor = '#d9edf7'; //Blue Color
document.getElementById(PID).style.backgroundColor = '#d9edf7'; //Blue Color
document.getElementById(PID).style.margin = '3px';
document.getElementById(BID).style.backgroundColor = '#d9edf7';
document.getElementById(BID).style.border = 'none';
innerDiv.className = "alert alert-info"
element.className = "alert alert-info"
}
if (cat == 'Warning') {
document.getElementById(ID).style.backgroundColor = '#fcf8e3'; //Orange Color
document.getElementById(PID).style.backgroundColor = '#fcf8e3'; //Orange Color
document.getElementById(PID).style.margin = '3px';
document.getElementById(BID).style.backgroundColor = '#fcf8e3';
document.getElementById(BID).style.border = 'none';
innerDiv.className = "alert alert-warning"
element.className = "alert alert-warning"
}
if (cat == 'Critical') {
document.getElementById(ID).style.backgroundColor = '#f2dede'; //Red Color
document.getElementById(PID).style.backgroundColor = '#f2dede'; //Red Color
document.getElementById(PID).style.margin = '3px';
document.getElementById(BID).style.backgroundColor = '#f2dede';
document.getElementById(BID).style.border = 'none';
innerDiv.className = "alert alert-danger"
element.className = "alert alert-danger"
}
}
// The below variables and for loop ensure that all sub messages are initially hidden, until the show/hide button is clicked
var curDiv
var curID
for (var i = 0; i < divCount; i++) {
curID = "P-" + i
curDiv = document.getElementById(curID)
curDiv.style.display = 'none';
}
// The function below is to assign an event to the button to show/hide the sub message
var f = function(a) {
var cDiv
for (var z = 0; z < divCount; z++) {
cDiv = "P-" + z
var div = document.getElementById(cDiv);
if (div.style.display !== 'none') {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
}
return false;
}
var elems = document.getElementsByClassName("toggle");
var idx
for (var i = 0, len = elems.length; i < len; i++) {
elems[i].onclick = f;
}
});
<div id="wrapper" class="header"> </div>
You're assigning all of your buttons the same onclick function event handler, and that function loops through all the divs and shows them or hides them.
An alternative approach would be to have the event handler toggle only the specific div that's associated with the button.
When you first create the button, you can assign an event handler to it immediately and pass in a reference to the div you want to hide:
var innerDiv = document.createElement("div");
innerDiv.id = PID
innerDiv.appendChild(document.createTextNode(message));
var btn = document.createElement("BUTTON");
// Immediately-invoked function expression to attach event handler to inner div:
(function(d){
btn.onclick = function(){ f(d); };
})(innerDiv);
Then just update your f function to accept as a parameter the div you want to toggle.
// The function below is to assign an event to the button to show/hide the sub message
function f(div){
if (div.style.display !== 'none') {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
return false;
}
You can then remove the last few lines of code where you're assigning the buttons to the elems collection and looping through it to attach an onclick function.
You can replace all of this - which loops over all divs
// The function below is to assign an event to the button to show/hide the sub message
var f = function(a) {
var cDiv
for (var z = 0; z < divCount; z++) {
cDiv = "P-" + z
var div = document.getElementById(cDiv);
if (div.style.display !== 'none') {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
}
return false;
}
var elems = document.getElementsByClassName("toggle");
var idx
for (var i = 0, len = elems.length; i < len; i++) {
elems[i].onclick = f;
}
with this, it delegates the click on the button in the wrapper and toggles the next object after the button
$('#wrapper').on("click",".toggle",function(e) { // notice the delegation
e.preventDefault(); // in case you forget type="button"
$(this).next().toggle();
});
Like this:
$(function() {
$('#wrapper').on("click", ".toggle", function(e) {
e.preventDefault();
$(this).next().toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="wrapper">
<div id="NewDiv-0" class="alert alert-info" style="background-color: rgb(217, 237, 247);">Debbie Teng joins PD Tax!********
<button id="btn-0" class="toggle" style="background-color: rgb(217, 237, 247); border: none;">show/hide message below</button>
<div id="P-0" class="alert alert-info" style="background-color: rgb(217, 237, 247); margin: 3px; display: none;">yadayada1</div>
</div>
</div>
I had to create a button inside a lookup field i have followed this page
http://bharathknight.blogspot.com/2015/03/create-button-inside-form-using.html i have added a event onchange the lookup value but the first alert is hitted but the second none and no button is displayed pleaase help me i'm stucked here
function createButton() {
alert("createButton");
var atrname = "xxxx";
if (document.getElementById(atrname ) != null) {
var fieldId = "field" + atrname ;
var elementId = document.getElementById(atrname + "_d");
var div = document.createElement("div");
div.style.width = "20%";
div.style.textAlign = "right";
div.style.display = "inline";
childDiv = elementId.getElementsByTagName('div')[0]
childDiv.style.display = "none";
elementId.appendChild(div, elementId );
div.innerHTML = '<button id="' + fieldId + '" type="button" style="margin-left: 4px; width: 50%;" >CRM Save Button</button>';
document.getElementById(atrname).style.width = "80%";
document.getElementById(fieldId ).onclick = function () { OnClickFunction(); };
}
}
function OnClickFunction() {
alert("clicked!");
}
With the introduction of turbo forms, things have changed a bit. If you want to access DOM, use document's parent element.
function createButton() {
var atrname = 'foobar';
if (window.parent.document.getElementById(atrname) != null) {
var fieldId = 'field' + atrname;
var elementId = window.parent.document.getElementById(atrname + '_d');
var div = window.parent.document.createElement('div');
div.style.width = '20%';
div.style.textAlign = 'right';
div.style.display = 'inline';
var childDiv = elementId.getElementsByTagName('div')[0];
childDiv.style.display = 'none';
elementId.appendChild(div, elementId);
div.innerHTML = '<button id="' + fieldId + '" type="button" style="margin-left: 4px; width: 50%;" >CRM Save Button</button>';
window.parent.document.getElementById(atrname).style.width = '80%';
window.parent.document.getElementById(fieldId).onclick = function () { OnClickFunction(); };
}
}
I'm attempting to make a tree view using JavaScript. I have a list of Divs created dynamically. A parent node that is showing and a child node that will not be showing. When you hit the button on the parent node it will call show('slow'). This works on IE8 and IE9, but when I test it with IE7, the child node will show with out it's CSS class. How can I make this work with IE7?
code in the main page
function CreateEventCategoryDiv(EventCategoryName) {
var NewEventCategoryNode = document.createElement('div');
NewEventCategoryNode.id = EventCategoryName + "Node";
if (TreeNodeCounter == 0 || (TreeNodeCounter % 2) == 0) {
NewEventCategoryNode.className = "EventCategoryNodesEven";
}
else {
NewEventCategoryNode.className = "EventCategoryNodesOdd";
}
NewEventCategoryNode.innerHTML = "<input type='button' value='+' id='ExpandButton' class='ExpandNodeButtons' onclick='ExpandNode(\"" + EventCategoryName + "\");' /> " + EventCategoryName;
var EventTree = document.getElementById("EventTree");
EventTree.appendChild(NewEventCategoryNode);
TreeNodeCounter++;
}
function ExpandNode(PassedNode) {
var ParentNode = CalendarObject.SearchCategoryNode(PassedNode);
if (ParentNode.IsChildrenShowing == false) {
ParentNode.ExpandNodes(CalendarObject.Months);
}
else if (ParentNode.IsChildrenShowing == true) {
ParentNode.CollapseNode(CalendarObject.Months);
}
}
This Part is called in the EventCategory Class to add the child nodes(sorry I forgot this one at first)
this.AddEventType = function (EventTypeNode) {
var NewElement = document.createElement('Div');
NewElement.id = EventTypeNode.DivAssociateId;
NewElement.innerText = EventTypeNode.Name;
if (this.NodesCount == 0 || (this.NodesCount % 2) == 0) {
NewElement.setAttribute("class", "EventTypeNodesEven");
}
else {
NewElement.setAttribute("class", "EventTypeNodesOdd");
}
NodesCount = this.EventTypeNodesArray.push(EventTypeNode);
$(NewElement).hide();
var ParentElement = document.getElementById("EventTree");
ParentElement.appendChild(NewElement);
this.NodesCount++;
};
This Part is in the CalendarGrid class
this.ExpandNodes = function (MonthArray) {
for (var x in this.EventTypeNodesArray) {
var SelectedNode = document.getElementById(this.EventTypeNodesArray[x].DivAssociateId);
if (this.IsChildrenShowing == false) {
$(SelectedNode).show('slow');
for (var y = 0; y < MonthArray.length; y++) {
var SelectedRow = document.getElementById(this.EventTypeNodesArray[x].Name + MonthArray[y].MonthName + "Row");
$(SelectedRow).show('slow');
}
}
}
this.IsChildrenShowing = true;
};
CSS Code:
.EventTypeNodesOdd
{
font-family:Arial;
font-weight:bold;
text-align:center;
height:27px;
background-color:#dbe2e6;
display:block;
}
.EventTypeNodesEven
{
font-family:Arial;
font-weight:bold;
text-align:center;
height:27px;
background-color:#f9fafb;
}
Try setting the class to whatever it should be after showing it.