I am trying to implement edit functionality for a HTML element.
Right now my html-pug code is as below
div
label(for="todo" id="todo" + index class="ind-todo-list") test1
button(type="submit" id="todo" + index class="btn" onclick="editTodo()" ) Edit
button(type="submit" id="todo" + index class="btn" onclick="deleteTodo()" ) Delete
Jquery is as below
$(document).ready(function() {
$(".ind-todo-list").on("click" , function(){
var todoid = $(this).attr("id");
var newInput = document.createElement("input");
newInput.type="text";
newInput.name="todo";
$("#" + todoid).html(newInput);
});
});
But everytime I am clicking at the test1 my page reloading again even after input field added.
What I am trying to achieve is
- when I click at test1, I will have input box opened, where I can edit the test1 and save changes. But I am stuck here.
Thank you.
Edit 1
I have added event.preventDefault() but still experiencing same same
$(document).ready(function() {
$(".ind-todo-list").on("click" , function(event){
event.preventDefault();
var todoid = $(this).attr("id");
console.log("Todoid " + todoid);
console.log($("#" + todoid).html());
var newInput = document.createElement("input");
newInput.type="text";
newInput.name="todo";
//newInput.id=todoid;
//$("#" + todoid).html("<input type='text' name='todo' id='"+todoid+"'>");
$("#" + todoid).html(newInput);
});
Edit 2 - ID fix
div
label(for="todo" id="todo" + index class="ind-todo-list") #{todo.todo}
button(type="submit" id="todoedit" + index class="btn" ) Edit
button(type="submit" id="tododeleteq" + index class="btn" ) Delete
$(".ind-todo-list").on("click" , function(e){
//add an event to prevent default action on the element
e.preventDefault();
});
});
Related
I need to create an enhanced transferbox, using HTML, JavaScript and JQuery.
I have a set of options a user can select from and associate with an attribute. The selection and deselection must be accomplished with two SELECT HTML elements (i.e., a transferbox). For example, these options can be a list of skill names.
When the 'add' button is clicked, the option(s) selected in the first SELECT element, along with an attribute (e.g. number of years from a text box) must be transferred from the source SELECT element to selected/destination SELECT element. The attribute must be displayed along with the item text in this second SELECT element (for example, the item displays the skill and the number of years).
When the 'remove' button is clicked, the selected option(s) in the second SELECT element must be moved back to the first SELECT element (in the original format .. without the attribute).
JSON should be the data format for initial selection setup and saving latest selections.
I want an initial set of selections and attributes to be set via JSON in an a hidden input field. I want the final set of selections to be saved to JSON in the same hidden input field.
Example HTML:
<input type="hidden" id="SelectionsId" value='[{ "id": "2", "attribute":"15"},{ "id": "4", "attribute":"3" }]' />
<!--<input type="hidden" id="SelectionsId" value='[]' />-->
<div>
<select class="MultiSelect" multiple="multiple" id="SelectFromId">
<option value="1">.NET</option>
<option value="2">C#</option>
<option value="3">SQL Server</option>
<option value="4">jQuery</option>
<option value="5">Oracle</option>
<option value="6">WPF</option>
</select>
<div style="float:left; margin-top:3%; padding:8px;">
<div>
<span>Years:</span>
<input id="YearsId" type="number" value="1" style="width:36px;" />
<button title="Add selected" id="includeBtnId">⇾</button>
</div>
<div style="text-align:center;margin-top:16%;">
<button title="Remove selected" id="removeBtnId">⇽</button>
</div>
</div>
<select class="MultiSelect" multiple="multiple" id="SelectToId"></select>
</div>
<div style="clear:both;"></div>
<div style="margin-top:40px;margin-left:200px;">
<button onclick="SaveFinalSelections();">Save</button>
</div>
Example CSS:
<style>
.MultiSelect {
width: 200px;
height: 200px;
float: left;
}
</style>
Visual of requirement:
Here's a solution to the challenge. The variables being setup at the start make this solution easy to configure and maintain.
When the page gets displayed, the SetupInitialSelections method looks at the JSON data in the hidden input field and populates the selected items.
When the 'Save' button clicked, the current selections are converted to JSON and placed back in the hidden input field.
Invisible character \u200C is introduced to delimit the item text and the attribute during display. This comes in to use if the item has to be removed and the original item text has to be determined so it can be placed back in the source SELECT element.
The selectNewItem variable can be set to true if you would like the newly added item to be selected soon after adding it to the SELECT element via the 'add' or 'remove' operations.
This solution supports multiple item selections. So multiple items can be added at once ... and similarly multiple items can be removed at once.
<script src="jquery-1.12.4.js"></script>
<script>
var savedSelectionsId = 'SelectionsId';
var fromElementId = 'SelectFromId';
var toElementId = 'SelectToId';
var includeButtonId = 'includeBtnId';
var removeButtonId = 'removeBtnId';
var extraElementId = 'YearsId';
var extraPrefix = " (";
var extraSuffix = " years)";
var noItemsToIncludeMessage = 'Select item(s) to include.';
var noItemsToRemoveMessage = 'Select item(s) to remove.';
var selectNewItem = false;
var hiddenSeparator = '\u200C'; // invisible seperator character
$(document).ready(function () {
SetupInitialSelections();
//when button clicked, include selected item(s)
$("#" + includeButtonId).click(function (e) {
var selectedOpts = $('#' + fromElementId + ' option:selected');
if (selectedOpts.length == 0) {
alert(noItemsToIncludeMessage);
e.preventDefault();
return;
}
var attribute = $("#" + extraElementId).val();
selectedOpts.each(function () {
var newItem = $('<option>', { value: $(this).val(), text: $(this).text() + hiddenSeparator + extraPrefix + attribute + extraSuffix });
$('#' + toElementId).append(newItem);
if (selectNewItem) {
newItem.prop('selected', true);
}
});
$(selectedOpts).remove();
e.preventDefault();
});
//when button clicked, remove selected item(s)
$("#" + removeButtonId).click(function (e) {
var selectedOpts = $('#' + toElementId + ' option:selected');
if (selectedOpts.length == 0) {
alert(noItemsToRemoveMessage);
e.preventDefault();
return;
}
selectedOpts.each(function () {
var textComponents = $(this).text().split(hiddenSeparator);
var textOnly = textComponents[0];
var newItem = $('<option>', { value: $(this).val(), text: textOnly });
$('#' + fromElementId).append(newItem);
if (selectNewItem) {
newItem.prop('selected', true);
}
});
$(selectedOpts).remove();
e.preventDefault();
});
});
// Setup/load initial selections
function SetupInitialSelections() {
var data = jQuery.parseJSON($("#" + savedSelectionsId).val());
$.each(data, function (id, item) {
var sourceItem = $("#" + fromElementId + " option[value='" + item.id + "']");
var newText = sourceItem.text() + hiddenSeparator + extraPrefix + item.attribute + extraSuffix;
$("#" + toElementId).append($("<option>", { value: sourceItem.val(), text: newText }));
sourceItem.remove();
});
}
// Save final selections
function SaveFinalSelections() {
var selectedItems = $("#" + toElementId + " option");
var values = $.map(selectedItems, function (option) {
var textComponents = option.text.split(hiddenSeparator);
var attribute = textComponents[1].substring(extraPrefix.length);
var attribute = attribute.substring(0, attribute.length - extraSuffix.length);
return '{"id":"' + option.value + '","attribute":"' + attribute + '"}';
});
$("#" + savedSelectionsId).val("[" + values + "]");
}
</script>
I'm currently adding some input fields to a div. There is also the option to remove the just added input fields.
Now the problem is, if you add 4 input fields and let's say you removed number 2.
You will get something like this
id=1
id=3
id=4
Now when you will add a new one it will add id=5.
So we end up with:
id=1
id=3
id=4
id=5
JS :
var iArtist = 1,
tArtist = 1;
$(document).on('click', '#js-addArtist', function() {
var artist = $('#js-artist');
var liData = '<div class="js-artist"><input id="artiestNaam_' + iArtist + '"><input id="artiestURL_' + iArtist + '"><span class="js-removeArtist">remove</span></div>';
$(liData).appendTo(artist);
iArtist++;
tArtist++;
});
$(document).on('click', '.js-removeArtist', function() {
if (tArtist > 1) {
$(this).parents('.js-artist').slideUp("normal", function() {
$(this).remove();
tArtist--;
});
}
});
$(document).on('click', '#js-print', function() {
var historyVar = [];
historyVar['artiestNaam_0'] = $('#artiestNaam_0').val();
historyVar['artiestURL_0'] = $('#artiestURL_0').val();
console.log(historyVar);
});
HTML :
<span id="js-addArtist">add</span>
<div id="js-artist">
<div class="js-artist">
<input id="artiestNaam_0">
<input id="artiestURL_0">
<span class="js-removeArtist">remove</span>
</div>
</div>
<span id="js-print">print</span>
For now it's okay.
Now for the next part I'm trying to get the data from the input fields:
historyVar['artiestNaam_0'] = $('#artiestNaam_0').val();
historyVar['artiestURL_0'] = $('#artiestURL_0').val();
How can I make sure to get the data of all the input fields?
Working version
You could do with a whole lot less code. For example purposes I'm going to keep it more simple than your question, but the priciple remains the same:
<input name="artiest_naam[]" />
<input name="artiest_naam[]" />
<input name="artiest_naam[]" />
The bracket at the end make it an array. We do not use any numbers in the name.
When you submit, it will get their index because it´s an array, which returns something like:
$_POST['artiestnaam'] = array(
[0] => "whatever you typed in the first",
[1] => "whatever you typed in the second",
[2] => "whatever you typed in the third"
)
If I would add and delete a hundred inputs, kept 3 random inputs and submit that, it will still be that result. The code will do the counting for you.
Nice bonus: If you add some javascript which enables to change the order of the inputs, it will be in the order the user placed them (e.g. if I had changed nuymber 2 and 3, my result would be "one, third, second").
Working fiddle
You could use each() function to go through all the divs with class js-artist:
$('.js-artist').each(function(){
var artiestNaam = $('input:eq(0)',this);
var artiestURL = $('input:eq(1)',this);
historyVar[artiestNaam.attr('id')] = artiestNaam.val();
historyVar[artiestURL.attr('id')] = artiestURL.val();
});
Hope this helps.
var iArtist = 1,
tArtist = 1;
$(document).on('click', '#js-addArtist', function() {
var artist = $('#js-artist');
var liData = '<div class="js-artist"><input id="artiestNaam_' + iArtist + '"><input id="artiestURL_' + iArtist + '"><span class="js-removeArtist">remove</span></div>';
$(liData).appendTo(artist);
iArtist++;
tArtist++;
});
$(document).on('click', '.js-removeArtist', function() {
if (tArtist > 1) {
$(this).parents('.js-artist').slideUp("normal", function() {
$(this).remove();
tArtist--;
});
}
});
$(document).on('click', '#js-print', function() {
var historyVar = [];
$('.js-artist').each(function(){
var artiestNaam = $('input:eq(0)',this);
var artiestURL = $('input:eq(1)',this);
historyVar[artiestNaam.attr('id')] = artiestNaam.val();
historyVar[artiestURL.attr('id')] = artiestURL.val();
});
console.log(historyVar);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="js-addArtist">add</span>
<div id="js-artist">
<div class="js-artist">
<input id="artiestNaam_0">
<input id="artiestURL_0">
<span class="js-removeArtist">remove</span>
</div>
</div>
<span id="js-print">print</span>
Initialize a count variable. This way if an input field is removed, a new id still gets initialized. To get the data for each of them, jQuery has a convenient each function to iterate over all elements.
Hope this helps
count = 0;
$("#add").on("click", function() {
count++;
$("body").append("<input id='" + count + "'</input>");
});
$("#remove").on("click", function() {
var index = prompt("Enter the index of the input you want to remove");
$("input:eq(" + index + ")").remove();
});
$("#log-data").on("click", function() {
$("input").each(function() {
console.log($(this).val());
});
});
#btn-group {
margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="btn-group">
<button id="add">Add Input Fields</button>
<button id="remove">Remove Input Fields</button>
<button id="log-data">Log Data</button>
</div>
I am trying to set up two button groups. A click on any button in the second group should add a new button to the first group. The new button shall get the same label as the clicked button.
var name = this.textContent works if the click handler is attached to a single button. How do you get the text content of the clicked button when the click handler is instead attached to a group of buttons?
HTML:
<body>
<div id="group1">
<button> nameA </button>
<button> nameB </button>
</div>
<hr>
<div id="group2">
<button> nameC </button>
<button> nameD </button>
</div>
</body>
Javascript:
$('#group2').on('click', function(event) {
var name = this.textContent // wrong!
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
JSFiddle Demo
Use event delegation:
$('#group2').on('click', 'button', function(event) {
var name = this.textContent
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
Second parameter in 'on' method can be selector string to filter the descendants of the selected elements that trigger the event.
Check this https://jsfiddle.net/q6b6g3xm/
In your case, this should be enought:
$('#group2 button').click(function(event) {
var name = this.textContent
var r = $('<input type="button" value="' + name + '">');
$("div#group1").append(r);
});
Prefer the RobHil solution if you other buttons will be created in #group2 after the execution of the jQuery code.
Else, I see two other possibilities:
$('#group2 button').each(function () {
var $button = $(this).click(function(event) {
var r = $('<input type="button" value="' + $button.text() + '">');
$("div#group1").append(r);
});
});
or:
$('#group2').click(function(event) {
var $button = $(event.target);
var r = $('<input type="button" value="' + $button.text() + '">');
$("div#group1").append(r);
});
But keep in mind the target depend on where you click if you have nested blocks in the clicked zone: https://api.jquery.com/event.target/
Here is my own approach to the problem. I modified HTML code a little by adding individual id to the buttons.
HTML:
<div id="group1" >
<button id="btn-A">nameA</button>
<button id="btn-B">nameB</button>
<button id="btn-C">nameC</button>
</div>
<hr />
<div id="group2">
<button id="btn-D">nameD</button>
<button id="btn-E">nameE</button>
<button id="btn-F">nameF</button>
</div>
JavaScript:
// click on the button
$(document).on('click','button', function(){
//store the value of the id and
// split it # '-' into array ['btn','A']
$id = $(this).attr('id').split('-');
// store the value at index 1 into $id
$id = $id[1];
//get the Id of the current div group
$divId = $(this).closest('div').attr('id');
//check which div group is current and
//Assign the reversed value as appropriate
if($divId === "group1"){
$addId = "#group2";
}else {
$addId = "#group1";
}
//Remove the button from the group
$(this).remove();
//Add the button to the second div group
$($addId).append('<button id="btn-'+$id+'">'+$(this).text()+'</button>');
});
I have an input field with Add button below it. Also have another Div class named .new-option-content
What I am trying to do is if anyone type something in the input filed and click the +ADD button this text of the input filed will append with a Check box inside .new-option-content div.
Here is the Fiddle
I tried with this but I guess with this process I can't get the result.
$( ".checklist-new-item-text" )
.keyup(function() {
var value = $( this ).val();
$( ".new-option-content" ).text( value );
})
.keyup();
I am not good with advance jquery. I did tried to find something similar but failed. I am not sure if this can be done with jquery.
Any help or suggestion will be appreciated.
$("#add").click(function(){
var newLabel = $("#optionInput").val();
if (!newLabel) return; //avoid adding empty checkboxes
var newOption = '<div class="checkbox"><label><input type="checkbox">' + newLabel +'</label></div>';
$(".new-option-content").append(newOption);
$("#optionInput").val(''); //clearing value
})
Fiddle: http://jsfiddle.net/has9L9Lh/8/
If you want to use it in multiple places on your page, you can try this modified version:
$(".new-option-add").click(function(){
var labelInput = $(this).parent().parent().find(".checklist-new-item-text")
var newLabel = labelInput.val()
if (!newLabel) return; //avoid adding empty checkboxes
var newOption = '<div class="checkbox"><label><input type="checkbox">' + newLabel +'</label></div>';
// where to append?
var listToAppend = $(this).attr("data")
$("." + listToAppend).append(newOption);
labelInput.val(''); //clearing value
})
We are using data attribute value on the button, to assign class name of the list, which need to be updated.
Fiddle: http://jsfiddle.net/has9L9Lh/18/
Here is how you can do it:
$(function() {
$('.new-option-add').on('click',function() {
var noc = $('.new-option-content'),
val = $('.checklist-new-item-text');
!val.val() || noc.append(
$('<div/>',{class:'checkbox'}).html(
$('<label/>').html( $('<input/>', {type:'checkbox'}) )
.append( ' ' )
.append( val.val() )
)
);
val.val('');
});
});
DEMO
And this should work for multiple sections:
$(function() {
$('.new-option-add').on('click',function() {
var section = $(this).closest('section'),
noc = $('.new-option-content', section),
val = $('.checklist-new-item-text', section);
!val.val() || noc.append(
$('<div/>',{class:'checkbox'}).html(
$('<label/>').html( $('<input/>', {type:'checkbox'}) )
.append( ' ' )
.append( val.val() )
)
);
val.val('');
});
});
DEMO
Many have answered, yet another option is to use .clone(), cause otherwise you can end up in a maintainence nightmare, so something like
$(".new-option-add").click(function() {
var checkbox = $(".checkbox:first").clone(), value;
value = $(".checklist-new-item-text").val();
checkbox.html(checkbox.html().replace('Sample 1', value));
checkbox.appendTo($(".new-option-content"));
})
http://jsfiddle.net/has9L9Lh/19/
you can do this by adding this code
on click event
$('#yourDiv').append(' <label><input id="chkbox" type="checkbox"> "+$('#yourText').val() +" </label>');
By using relative references I am able to remove items which have been added to the list within a specfic part of the form. For example, by adding a requirement it can be deleted just from the requirement.
My issue is two fold:
Adding an item to references adds it to all three categories
When I try to add values to the other sections (qualifications) it says my input was blank.
http://jsfiddle.net/spadez/9sX6X/60/
var container = $('.copies'),
value_src = $('#current'),
maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
value_src.focus();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
value_src.focus();
$(this).parents('.line').remove();
currentFields--;
});
Is it possible to modify this code without repeating it for each section, by using relatively references such as "parent" for example. I want to use this same script for all three sections but have it so each list is independant.
I'm new to javascript so I was wondering if this is possible because I only managed to get it working on the delete.
You have to use this to get the current element. In your case this refers to the button which was clicked.
The next step is to get the input box which belongs to the button. E.g. $(this).prev(); like in this example:
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
http://jsfiddle.net/9sX6X/62/
The same is also true for your appending part. Your are appending your html to all three elements which match $('.copies'). Instead you have to try to get there from this.
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var copies = $(this).parent().prev();
http://jsfiddle.net/9sX6X/63/
I would suggest adding a wrapping div to each section.
<div class="section">
<h4>Requirements</h4>
<div class="copies"></div>
<div class="line">
<input id="current" type="text" name="content" placeholder="Requirement" />
<input type="button" value="Add" class="add" />
</div>
</div>
Then you can do this:
var $section = $(this).closest(".section");
$(html).appendTo($section.find(".copies"));
This will add to just the related .copies element instead of to all .copies as your code does now. A similar approach can be used for all other elements as well.