add a button with jQuery for an existing jQuery button - javascript

Can someone please help me/explain how can I do this or if it's possible?
I have a simple html code for a grocery list :
<!DOCTYPE html>
<html>
<head>
<title>Let's buy...</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<h2 class="title">My grocery list<span id="counter"></span> </h2>
<ul id="list-items"></ul>
<div id="newItemButton"><button href="#" id="showForm">new item</button></div>
<form id="newItemForm">
<input type="text" id="itemDescription" placeholder="Add item..."/>
<input type="submit" id="addButton" value="add" />
</form>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<!-- <script type="text/javascript"
src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script> -->
<script type="text/javascript" src="js/javascript.js"></script>
</body>
</html>
And I am the user is adding elements to the list - when the user adds an item, that item comes with a button. Now, I want that button "change item" to add 4 more buttons with append(), and I want each button, when clicked to change the color of the item eg red, green, orange and grey - depending on user preference.
I am trying to add those buttons but I don't seem to add it, it does not appear on the page - just to say - I tried to add only one button :) .
Here is my jQuery code ... :
$(function() {
let $list, $newItemForm, $newItemButton;
let item = '';
$list = $('ul');
$newItemForm = $('#newItemForm');
$newItemButton = $('#newItemButton');
function updateCount() {
let items = $('li').length;
$('#counter').text(items);
}
updateCount();
$newItemButton.show();
$newItemForm.hide();
$('#showForm').on('click', function() {
$newItemButton.hide();
$newItemForm.show();
});
$newItemForm.on('submit', function(e) {
e.preventDefault();
let text = $('input:text').val();
$list.append('<li>' + text + '<button id="btn-change">change item</button><hr></li>');
$('input:text').val('');
updateCount();
});
and this is the = 'button adding process' :
$('#btn-change').one('click', function() {
let b = $('<input/>').attr({
type: "button",
id: "hot",
value: 'hot'
});
$("button").append(b);
});

There are other things that need to be addressed such as multiple buttons, how you instantiate the event handler and more. However to just answer your "why does my new input not appear".
A button element should not contain and input element. You can see why that would not make sense. Thus to create a new input of type button after that and not append TO that so, use the .after. Now assume that the actual clicked on is the one we want to append to we can use this and append to our button with id btn-change
$('#btn-change').one('click', function() {
let b = $('<input/>').attr({
type: "button",
id: "hot",
value: 'hot'
});
$(this).after(b);
});
Here is another option simply using a different method that performs the same function, does the same thing but perhaps the name makes the intent more clear.
$('#btn-change').one('click', function() {
let b = $('<input/>').attr({
type: "button",
id: "hot",
value: 'hot'
});
b.insertAfter(this);
});
Now we can add a button, we observe that we added this button we are clicking dynamically, thus we need to allow our event handler to be dynamic as well, that is attach it to a container for the button.
list-items is our container, so we attach to that.
$('#list-items').one('click', '#btn-change',function() {
let b = $('<input/>').attr({
type: "button",
id: "hot",
value: 'hot'
});
b.insertAfter(this);
});
Now that we have our event handler we also note that the duplicate id is not valid so we modify to use a class instead of an id.
$('#list-items').one('click', '.btn-change',function() {
let b = $('<input/>').attr({
type: "button",
class: "hot",
value: 'hot'
});
b.insertAfter(this);
});
Now that we have some explanation out of the way, lets do a solution
$(function() {
let $list, $newItemForm, $newItemButton;
let item = '';
$list = $('#list-items'); // use faster id
$newItemForm = $('#newItemForm');
$newItemButton = $('#newItemButton');
function updateCount() {
let items = $list.find('li').length; // get inside our list
$('#counter').text(items);
}
updateCount();
$newItemButton.show();
$newItemForm.hide();
$newItemButton.on('click', function() {
$newItemButton.hide();
$newItemForm.show();
});
function addButton(place, b) {
let bt = $('<input/>').attr({
type: "button",
class: b + "button colorbutton",
value: b
}).data("colorclass", b + "thing");
bt.insertAfter(place);
}
// perhaps change to button type not submit type?
$newItemForm.on('submit', function(e) {
e.preventDefault();
let text = $('#itemDescription').val(); // use fast id
text = text=""?"new":text;//avoid empty text
$list.append('<li><span class="desc">' + text + '</span><button type="button" class="btn-change">change item</button><hr></li>');
$('#itemDescription').val('');
updateCount();
});
$('#list-items').on('click', '.colorbutton', function() {
$(this).parent().find('.desc')
.removeClass("hotthing greenthing orangething greything")
.addClass($(this).data("colorclass"));
});
//Note the change here from discussion, still adds the buttons but more modular, disables button to avoid second click vs the .one, works for new items
$('#list-items').on('click', '.btn-change', function() {
$(this).prop("disabled", true); // only add once so disable it
// add the color buttons, matches classes in css
addButton(this, "hot");
addButton(this, "green");
addButton(this, "orange");
addButton(this, "grey");
});
});
.hotbutton {
color: red;
}
.greenbutton {
color: green;
}
.orangebutton {
color: orange;
}
.greybutton {
color: grey;
}
.hotthing {
background-color: red;
}
.greenthing {
background-color: green;
}
.orangething {
background-color: orange;
}
.greything {
background-color: grey;
}
#list-items {
border: solid lime 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
<h2 class="title">My grocery list<span id="counter"></span> </h2>
<ul id="list-items"></ul>
<div id="newItemButton"><button type="button" id="showForm">new item</button></div>
<form id="newItemForm">
<input type="text" id="itemDescription" placeholder="Add item..." />
<input type="submit" id="addButton" value="add" />
</form>
</body>

The problem that you are dealing with is that you try to fire an event from a dynamic generated element. The #btn-change element was not loaded in the page when you attached the event. Based on the documentation you can add a selector. You will have to attach the event into a stable element of your page e.g ul#list-items
so your code would look like this
$("ul#list-items").one('click','#btn-change', function() {
let b = $('<input/>').attr({
type: "button",
id: "hot",
value: 'hot'
});
$("button").append(b);
});
Or you could attach the event grammatically.
Also i would like to suggest you to use classes instead of id for elements that would exist multiple times on the same page (e.g the <button id='btn-change'></button>) the id must be unique in your page.
So the code that i would suggest would look like this
$newItemForm.on('submit', function(e) {
e.preventDefault();
let text = $('input:text').val();
$list.append('<li>' + text + '<button class="btn-change">change item</button><hr></li>');
$('input:text').val('');
updateCount();
});
changed the id='btn-change' to class='btn-change'
and the code of the btn-change click event
$('ul#list-items').one('click','.btn-change', function() {
let btnContainer = $("<div></div>").css("display","inline-block").attr({
class: "btn-container"
});
btnContainer.append(
$('<input/>').attr({
type: "button",
class: "hot", //use class instead of id in case you generate more than 1 element
value: 'hot'
})
).append(
$('<input/>').attr({
type: "button",
class: "green", //use class instead of id in case you generate more than 1 element
value: 'green'
})
).append(
$('<input/>').attr({
type: "button",
class: "grey", //use class instead of id in case you generate more than 1 elements
value: 'grey'
})
).append(
$('<input/>').attr({
type: "button",
class: "orange", //use class instead of id in case you generate more than 1 element
value: 'orange'
})
);
btnContainer.insertBefore(this);
$(this).hide();//or remove based on what you want to achieve
});
here I am using the .btn-change as selector and I am creating a container element to hold the four buttons then i add the container of four buttons before the .btn-change button and hide the button.
You can add later the part of code that will remove/hide the container of the four buttons and show the .btn-change button

Related

Get dynamically created element that was click javascript

I'm trying to track what buttons users click via javascript/jquery. I have the following code
$(document).on('click', '[data-tracker]', function( event ) {
var target = event.target;
var targetName = $(target).data('tracker');
console.log(targetName);
});
<button data-tracker="test1">test1</button>
<i data-tracker="test2">test2</i>
<img data-tracker="test3">
At the moment this works as I want it to. When someone clicks on an element on the page that has the data-tracker attribute I log the value in the console.
I'm using datatables on some pages which dynamically creates elements from json returned from the server. I can't figure out how to record elements that have been dynamically created.
So all in all I want 1 function that will check if a user clicks on an element with the data-tracker attribute and output it's value to the console.
First of all instead of something like this
$(document).on('click', '[data-tracker]', function( event ) {
var target = event.target;
var targetName = $(target).data('tracker');
console.log(targetName);
});
You can do this
$(document).on('click', '[data-tracker]', function() {
var targetName = $(this).data('tracker');
console.log(targetName);
});
Secondly, the reason of this behavior may be because .data() function works that way
Store arbitrary data associated with the specified element. Returns the value that was set.
So when you dynamically add an element with attribute data-tracker there is no value set because it was not stored. So instead of using .data() just use .attr().
$(document).on('click', '[data-tracker]', function() {
var targetName = $(this).attr('data-tracker');
console.log(targetName);
});
Here is a snippet
$(document).on('click', '[data-tracker]', function() {
console.log($(this).attr('data-tracker'));
});
var num = 0;
$("#addElement").on('click', function() {
$("<div>").attr('data-tracker', 'test value ' + num).html('Test value' + num).appendTo(".content");
num++;
});
[data-tracker] {
cursor: pointer;
color: #F00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="addElement">Add element</button>
<div class="content">
<div data-tracker="value1">Value 1</div>
<div data-tracker="value2">Value 2</div>
<div>Test</div>
<div data-tracker="value3">Value 3</div>
<div data-tracker="value4">Value 4</div>
</div>
Your code looks OK to me. You are probably making some mistake when added elements with JSON, make sure you get that correct.
Here I've added a button to add elements to the page dynamically, you can verify
$(document).on('click', '[data-tracker]', function( event ) {
var target = event.target;
var targetName = $(target).data('tracker');
console.log(targetName);
});
$("#new").click(function(){
$("#d").append(`<button data-tracker="test1">test1</button>
<i data-tracker="test2">test2</i>
<img data-tracker="test3">`)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="d">
<button data-tracker="test1">test1</button>
<i data-tracker="test2">test2</i>
<img data-tracker="test3">
</div>
<br/>
<button id="new">Add</button>
I am assuming the data-tracker is a class name. And here is a example of how you adding a onclick event to all element with the same class name
a = document.getElementsByClassName("data-tracker")
for (var key in a) {
if (a.hasOwnProperty(key) && Number.isInteger(parseInt(key))) {
a[key].addEventListener("click", function(){console.log('hi')});
}
}
<input type="button" class="data-tracker" value="button1"></input>
<input type="button" class="" value="button2"></input>
<input type="button" class="data-tracker" value="button3"></input>

How to append multiple parent and child div in one single div using keypress jquery

I am developing a system in which main requirement is that user A press add more button and user will fill up data in it. Then add more again and more data.
What I really need to do is to embed 1st add more data and 2nd add more data in one div using keypress events.
For e.g,
user starting writing in 1st text field of 1st add more, then 2nd text field of 1st add more so it should embed this data in one div named: one
user starting writing in 1st text field of 2nd add more, then 2nd text field of 2nd add more so it should embed this data in one div named: two
At the end I want to embed both one and two divs in one single div.
Problem:
It does not including and embed the fields recursively in final div nor keypress is working as expected.
Als returning error $(...).text(...).append is not a function. That is coming in last line of code.
Jquery code:
children_container = $('<div/>', {'class': 'children_new_package_itineraries_container'});
if (children_container.length > 0) {
$("#day_new_package_itineraries_field").on('keypress change', function () {
$('<div/>', {
'class': 'day_new_package_itineraries_container',
'html': $(this).val()
});
});
$("#title_new_package_itineraries_field").on('keypress change', function () {
$('<div/>', {
'class': 'title_new_package_itineraries_container',
'html': $(this).val()
});
});
children_container.append($(".day_new_package_itineraries_container").text().append($(".title_new_package_itineraries_container").val()));
$(".preview_container").html(children_container);
}
Desired Output:
<div class="preview_container">
<div class="children_1493016690115_container">
<div class="day_1493016690115_container">Day: 123</div>
<div class="title_1493016690115_container">Title: xyz</div>
</div>
<div class="children_1493016960131_container">
<div class="day_1493016960131_container">Day: 123</div>
<div class="title_1493016960131_container">Title: xyz</div>
</div>
</div>
P.S: I am sitting _1493016690115_ or _1493016960131_ these values dynamically so that's not the issue how I am dealing these inputs dynamically.
You can append where you are creating element
children_container = $('<div/>', {'class': 'children_new_package_itineraries_container'});
if (children_container.length > 0) {
$("#day_new_package_itineraries_field").on('keypress change', function () {
if($(".day_new_package_itineraries_container").length) {
$(".day_new_package_itineraries_container").html($(this).val());
}else{
children_container.html($('<div/>', {
'class': 'day_new_package_itineraries_container',
'html': $(this).val()
}));
}
});
$("#title_new_package_itineraries_field").on('keypress change', function () {
if($(".title_new_package_itineraries_container").length) {
$(".title_new_package_itineraries_container").html($(this).val());
}else{
children_container.append($('<div/>', {
'class': 'title_new_package_itineraries_container',
'html': $(this).val()
}));
}
});
$(".preview_container").html(children_container);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div class="preview_container"></div>
<input id= "day_new_package_itineraries_field">
<input id= "title_new_package_itineraries_field">

Issue in dynamically added select list

in my project,(Edit page) i have an input box that contain the value from db. and place a div over that input box(when page loading that div is not shown). my need is when i am clicking on that input box i want to enable the div and show as a drop down select list. i am using following code,
http://jsfiddle.net/wzPYf/1/
<div class="role">
<div style="float:left;">In Rotary Club of Puthencruz : </div>
<div class="currentrole"><input type="text" value="#Model.Mem_Role" name="Mem_Role" id="memrole"/></div>
<div class="allrole"></div>
</div>
//jquery
$(document).ready(function () {
$('#memrole').click(function () {
$('.allrole').attr('disabled', false);
var arr = [
{ val: 'member', text: 'Member' },
{ val: 'president', text: 'President' }
];
var sel = $('<select>').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
$('.allrole').html(sel);
});
});
//css
.role {
position:relative;
display:inline-block;
}
.currentrole {
position: absolute;
margin-left:100%;
width:200%;
}
.allrole {
position:absolute;
width:150px;
height:20px;
margin-left:100%;
display:none;
}
But my jquery part is not working, the dropdown select list is not displayed.
Change your code to this -
$(document).ready(function () {
$('#memrole').click(function () {
var arr = [
{ val: 'member', text: 'Member' },
{ val: 'president', text: 'President' }
];
var sel = $('<select>');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val)
.text(this.text));
});
$('.allrole').html(sel);
$('.allrole').show();
});
JSFiddle.
The mistake that you were making was - to show a hidden div, you need to call jQuery's show method on it. Setting disabled attribute to false doesn't work here.
Also you can simply create a select element by calling $(''), no need to append it to a body, since you are already attaching it to the .allrole div later. Next, rather than assigning the the select element with options as a text, I simply appended it to the .allrole div.
If you want to show the div which is display:none or visibility:hidden just use $(yourselector).show(); So your code would be
$('.allrole').show(); instead of
$('.allrole').attr('disabled', false);
The working demo is here Refer show()

Performing Action while clicking a text to remove a Div

I have an Example what I get this from one of my previous post .I am trying to upgrade this with my need but I failing . I guess it's because of my lack of knowledge in jquery and JavaScripts . But I need this badly .
Here is Live demo in js fiddle :http://jsfiddle.net/qzKWD/5/
What I have now:
There you can see I have a button . If I click the button it will open a Div with Editable input , where I can rename the input and save . you can create many div by clicking the button and rename as you want .
What I am trying to do
What I was trying to Do is that ,I added a "X" text there . When I click the button "START" new div created with input to change name , also with this "X" text . What I am mainly trying is .. before I rename he input if I don't what that div I can remove the div with input by clicking the "X" text . SO that mean "X" will act as a close of that Div .But I am not finding any way to do that . May be because of my lacking of knowledge . If there is any solution or way it will be Excellent .
My code :
HTML
<button id="createDiv">Start</button>
<div id="results"></div>
CSS
#createDiv, #results span { cursor: pointer; }
#results div {
background: #FFA;
border: 1px solid;
width:auto;
}
#results input[type=text] {
border: none;
display: none;
outline: none;
}
.clickToCancleIcon{
float: right;
}
.new-folder{
height:30px;
float:left;
}
JS
// Call for document .onload event
$(function() {
// Normal Click event asignement, same as $("#createDiv").click(function
$("#createDiv").on("click", function(e) {
// Simply creating the elements one by one to remove confusion
var newDiv = $("<div />", { class: "new-folder" }), // Notice, each child variable is appended to parent
newInp = $("<input />", { name: "inpTitle[]",style:"display:block ;float:left; border:solid 1px #fa9a34", type: "text", value: "Unnamed Group", class: "title-inp" }).appendTo(newDiv),
newSpan = $("<span />", { id: "myInstance2",style:"display:none; float:left;", text: "Unnamed Group", class: "title-span" }).appendTo(newDiv),
clickToCancle = $("<a />", { text: "X", class: "clickToCancleIcon" }).appendTo(newDiv);
// Everything created and seated, let's append this new div to it's parent
$("#results").append(newDiv);
});
// the following use the ".delegate" side of .on
// This means that ALL future created elements with the same classname,
// inside the same parent will have this same event function added
$("#results").on("click", ".new-folder .title-span", function(e) {
// This hides our span as it was clicked on and shows our trick input,
// also places focus on input
$(this).hide().prev().show().focus();
});
$("#results").on("blur", ".new-folder .title-inp", function(e) {
// tells the browser, when user clicks away from input, hide input and show span
// also replaces text in span with new text in input
$(this).hide().next().text($(this).val()).show();
});
// The following sures we get the same functionality from blur on Enter key being pressed
$("#results").on("keyup", ".new-folder .title-inp", function(e) {
// Here we grab the key code for the "Enter" key
var eKey = e.which || e.keyCode;
if (eKey == 13) { // if enter key was pressed then hide input, show span, replace text
$(this).hide().next().text($(this).val()).show();
}
});
})
Just add the following code,
clickToCancle.click(function() {
$(newDiv).remove();
});
After,
clickToCancle = $("<a />", { text: "X", class: "clickToCancleIcon" }).appendTo(newDiv);
Or you can done this by,
clickToCancle = $("<a />", { text: "X", class: "clickToCancleIcon" }).appendTo(newDiv).click(function() {
$(newDiv).remove();
});
See the live DEMO

Need help about a function

I am new at Javascript and jQuery. I need help with something like:
<script type="text/javascript">
$(window).load(function(){
$('#createDiv').click(function (){
$("<div/>").html("<span id='myInstance2' style='display: block;'>New Folder</span>").css("display", "none").appendTo("#results").fadeIn();
});
});
</script>
I have this function to click and create a new <span> tag with a text. You can see I have an ID myInstance2. So what I am trying to do is when I click and the span is created, I would like to make this span live-editable. Like I can rename this "New folder" into whatever I want.
If anyone can help it would be great. Thanks in advance and sorry for my bad English :)
If I catch what I think you're trying to do, it's not quite feasable the way you imagine. However, there are tricks. The following is one of them. The idea is to insert a "hidden" input where the span is, then create functions to show the input and hide span when needed (like when user clicks on span. Something like so:
jsFiddle
HTML
<button id="createDiv">Start</button>
<div id="results"></div>
CSS
#createDiv, #results span { cursor: pointer; }
#results div {
background: #FFA;
border: 1px solid;
margin: 1em;
padding: 1em 1em 2em;
}
#results input[type=text] {
border: none;
display: none;
outline: none;
}
JavaScript
// Call for document .onload event
$(function() {
// Normal Click event asignement, same as $("#createDiv").click(function
$("#createDiv").on("click", function(e) {
// Simply creating the elements one by one to remove confusion
var newDiv = $("<div />", { class: "new-folder" }), // Notice, each child variable is appended to parent
newInp = $("<input />", { type: "text", value: "New Folder", class: "title-inp" }).appendTo(newDiv),
newSpan = $("<span />", { id: "myInstance2", text: "New Folder", class: "title-span" }).appendTo(newDiv);
// Everything created and seated, let's append this new div to it's parent
$("#results").append(newDiv);
});
// the following use the ".delegate" side of .on
// This means that ALL future created elements with the same classname,
// inside the same parent will have this same event function added
$("#results").on("click", ".new-folder .title-span", function(e) {
// This hides our span as it was clicked on and shows our trick input,
// also places focus on input
$(this).hide().prev().show().focus();
});
$("#results").on("blur", ".new-folder .title-inp", function(e) {
// tells the browser, when user clicks away from input, hide input and show span
// also replaces text in span with new text in input
$(this).hide().next().text($(this).val()).show();
});
// The following sures we get the same functionality from blur on Enter key being pressed
$("#results").on("keyup", ".new-folder .title-inp", function(e) {
// Here we grab the key code for the "Enter" key
var eKey = e.which || e.keyCode;
if (eKey == 13) { // if enter key was pressed then hide input, show span, replace text
$(this).hide().next().text($(this).val()).show();
}
});
})
what you can do is put a delegated event handler on the enclosing, static element where span will reside #results. The handler will hide the span and reveal an input. I don't know your code well enough but you likely want the id on the input instead of the span. You did not say you wanted to go from editable back to "read-only" so I did not do that.
DEMO
$('#createDiv').on('click', function () {
var str = "Click here to edit it"; // New Folder
$("<div/>").html("<span id='myInstance2' class='editToggler' style='display: block;'>" + str + "</span><input class='editToggler' style='display: none' value='" + str + "'/>").appendTo("#results").fadeIn();
$(this).off('click');
});
$('#results').on('click', 'span', function () {
$('.editToggler').toggle();
});
This should work and is much simpler than other answers (imo):
<script type="text/javascript">
$(window).load(function(){
$('#createDiv').click(function (){
$("<div />").html("<span onclick='$(this).html(prompt(\"Rename \"+$(this).html()))' id='myInstance2' style='display: block; cursor:pointer;'>New Folder</span>").css("display", "none").appendTo("#results").fadeIn();
});
});
</script>
When you click your span, you will be prompted for its new name. To visual represent that your created the span is clickable, I also added cursor:pointer to the style for the span.
Demo: http://jsfiddle.net/XJ6Cn/
Edit: P.S: Do you create more than one spanusing this method? If so, you should create the ids dynamically, because ids are meant to be unique. If you want a string to be the same for all spans, you can set it as a class instead.

Categories

Resources