I am using angularjs, please see this code in http://jsfiddle.net/6XDeV/
what I want:
When click on the button add it will appear $scope.todotest value a long with the value in textbox.
My problem:
When I add the first it not show the date along with the text in textbox and if I add the second time it will appear. And I want to appear since the first time that click on add button.
Anyone know about this help me to fix please, thanks.
That's because at the first time you call addTodo the todotest is undefined.
Just move the $scope.todotest = '23' before the push, like this:
$scope.addTodo = function() {
$scope.todotest = '23';
$scope.todos.push({text:$scope.todoText,test:$scope.todotest, done:false});
$scope.todoText = '';
};
Example: http://jsfiddle.net/757d3/
You're setting the $scope variable todotest after adding a new item to your array todos.
$scope.addTodo = function() {
$scope.todos.push({text:$scope.todoText,test:$scope.todotest, done:false});
$scope.todoText = '';
$scope.todotest = '23'; // This should be done before the push
};
See updated fiddler here.
add this line $scope.todotest = '23'; before this $scope.addTodo = function() {
check this[code] http://jsfiddle.net/6XDeV/1/[/code]
Related
I posted this question before, among others. But it was suggested I need to ask a more specific or focused question.
I am working on an output history log on a single page. And I want to make it so each output it's self is contained in box object that can be closed or deleted individually. Like this.
Now I have managed to get everything working to the point where it will nicely output to a box with a close button. However the close button it's self will not function in this case.
So, I am trying to output it like this...
HTML:
<p>History log:</p><br><div style="white-space:pre-wrap"><ul
id="outputListItem" class="boxcontainer"></ul></div>
SCRIPT:
document.getElementById("Add").onclick = function(e) {
convertOutput();
}
function convertOutput(){
//this is the part I have been trying to get working
convertOutput.addEventListener('close', function() {
this.parentElement.style.display = 'none';
}
});
var output = document.getElementById("output").value;
var li = document.createElement('li');
li.className = "containedboxes";
var dateTime = todayDateTime();
li.innerHTML = "<time id='time'>" + dateTime +"</time><br /> <br />"+ output
+"<br /><br /><span class='close'>×</span>";
document.getElementById('outputListItem').prepend(li);
}
And the script to close the box:
var closebtns = document.getElementsByClassName("close");
var i;
for (i = 0; i < closebtns.length; i++) {
closebtns[i].addEventListener("click", function() {
this.parentElement.style.display = 'none';
});
}
It was suggested to me on the last question I posed I should use convertOutput() right after addEventListener() loop immediately after it. If this is how you do it, i am still quite new to JavaScript, so not sore how to properly do this. I created a fiddle for this also, but for some reason I can't get the script to run properly in the fiddle, But all the code is there to see.
I am looking to solve this using vanilla JavaScript.
I created an example for you. Hopefully this helps you get going :) A couple things to note, I use a data attribute to store the index for the item in the array, so you can delete it when you click on the list item.
document.addEventListener('DOMContentLoaded', function(){
let nameEl = document.querySelector("#name");
let submitEl = document.querySelector("#submit-name");
let historyEl = document.querySelector(".history-list");
let historyList = [
{ name: 'Mitch'},
{ name: 'Max'},
{ name: 'Mike'},
];
function addToList(arr) {
// Clear up list and then update it
while(historyEl.firstChild) {
historyEl.removeChild(historyEl.firstChild);
}
// Update the list with the historyList
for(let item in historyList) {
let name = historyList[item].name;
let listContent = document.createElement("li");
listContent.textContent = name;
// We will use the index to remove items from the list
listContent.setAttribute('data-value', item);
listContent.addEventListener("click", removeFromList)
historyEl.appendChild(listContent);
}
}
function removeFromList(index) {
// Takes the index of the object, and will later remove it
console.log("Removed Item " + this.dataset.value);
historyList.splice(index, 1);
addToList(historyList);
}
addToList(historyList);
submitEl.addEventListener("click", function(event) {
if(nameEl.value) {
// Add the name to the start of the history list array.
historyList.unshift({ name: nameEl.value})
nameEl.value = '';
// Update the dom with the new array
addToList(historyList);
}
});
});
<label for="name">Type Name</label>
<input type="text" name="name" id="name">
<button id="submit-name">Submit Name</button>
<ul class="history-list"></ul>
Hopefully this gives you a good idea on how to get the task done and let me know if you have any questions :)
Your boxes don't respond to the click event simply because your script crashes before the events even get attached to it.
The following block right at the beginning:
document.getElementById("Add").onclick = function(e) {
convertOutput();
}
tries to add a click listener to the HTML element Add which does not exist. If you either remove the code block or add the appropriate element your boxes will have it's click functionality.
I have a form that shows up when each row in a table is double clicked. The values of this form can be updated and the form should be submitted with all row changes. But each time I double click on a row and edit the values of that form for that row, the previous values I had changed get overwritten. In order to work around this, I tried adding all the changes to a map with the row id as the key and the values of the form as the value. But the form still won't update with the new values. Here is a fiddle to demonstrate what I mean:
https://jsfiddle.net/4fr3edk7/2/
If I double click on the row that says "Adam Smith" and change that name to John Doe, when I double click on the second row and then double Click on "Adam Smith" again, it should say "John" on the first textbox and "Doe" on the second one. But the new value never seems to save.
This code snippet loops through each key, then loops through each value of that key:
for(var i = 0; i<key.length; i++){
var getval = globalchanges[key[i]];
for(var k=0; k<getval.length; k++){
$("#input1").val(getval[0]);
$("#input2").val(getval[1]);
}
}
How can I get the new changes to save? (The table rows don't have to show the changes, just the textbox values). Any help would be appreciated.
First, as mentioned by #Taplar you are binding the click event multiple times. Your approach is close enough, the idea of storing the changes is valid. You should have 2 functions, store the changes on button click and the second one to retrieve the changes by id.
Updated Fiddle
This function will get the values of the form and will store in on a global object
function setMap(id){
var firstrow = $("#input1").val();
var secondrow = $("#input2").val();
globalchanges[id] = [firstrow,secondrow];
}
This other function will check if the global object has values for the passed id, if not, it will use the values on the row
function getMap(id, tr){
if(globalchanges[id] != undefined && globalchanges[id].length == 2){
$("#input1").val(globalchanges[id][0]);
$("#input2").val(globalchanges[id][1]);
}
else{
$("#input1").val($(tr).find('td').eq(1).text());
$("#input2").val($(tr).find('td').eq(2).text());
}
}
Please note there are also changes on the dbclick and click events, they should be separated
$("#table tr").dblclick(function(){
$("#txtbox-wrapper").css({"display" : "block"});
var id = $(this).find('td').eq(0).text();
$('#id').val(id);
getMap(id,this);
});
$("#savebtn").click(function(){
var id = $('#id').val();
setMap(id);
});
And that we added and additional input to store the id on the form.
You are going to need to rethink your logic because of this part
$("#table tr").dblclick(function(){
$("#txtbox-wrapper").css({"display" : "block"});
var id = $(this).find('td').eq(0).text();
$("#input1").val($(this).find('td').eq(1).text());
$("#input2").val($(this).find('td').eq(2).text());
$("#savebtn").click(function(){
addToMap(id);
});
});
-Every time- you double click a table row you are adding a new click binding to the savebtn element. This means if you double click both rows, when you click that button it will execute addToMap for both ids. You may have other issues with your logic relying on only two other inputs for multiple rows, but this double/triple/+ binding is going to bite you.
There are few changes required in your logic as well as implementation.
1: Do not bind save event inside row click.
2: You are selecting the value in row double click event from td element. You need to update this element to keep your logic working
3: Keep track of which row is getting updated.
Updated Code
var globalchanges = {};
var rowSelected = null;
$("#table tr").dblclick(function() {
$("#txtbox-wrapper").css({
"display": "block"
});
rowSelected = $(this).find('td').eq(0).text();
$("#input1").val($(this).find('td').eq(1).text());
$("#input2").val($(this).find('td').eq(2).text());
});
$("#savebtn").click(function() {
addToMap(rowSelected);
});
function addToMap(row) {
var array = [];
var changes = {};
var firstrow = $("#input1").val();
var secondrow = $("#input2").val();
array.push(firstrow, secondrow);
globalchanges[row] = array;
makeChanges(row);
}
function makeChanges(row) {
var key = Object.keys(globalchanges);
console.log(key);
$("#table tr td").each(function(k, v) {
if ($(v).text() == key) {
$(v).next().html(globalchanges[row][0]);
$(v).next().next().html(globalchanges[row][1]);
globalchanges = {};
}
});
}
Working fiddle : https://jsfiddle.net/yudLxsgu/
I made a dropdown with a html value change result, so after every click i get the new html value:
$("#list li a").on('click',function(){
var val=$(this).html();
$("#selector").html(val);
});
Simple enough to understand. What I'm trying to do is in the new reload, the html (val) stays on the new load. How can one do this?
I was thinking of HTML5: localStorage but really not sure if this is right?
localStorage.setItem(currentlist, $('#selector').val());
window.onload = function() {
var name = localStorage.getItem(currentlist);
}
Not sure if Im doing this right or missing something. But this is where I'm at. Is this the right way to go...or do some cookie state?
JSFIDDLE DEMO
$("#list li a").on('click',function(){
var val = $(this).html();
$("#selector").html(val);
localStorage.setItem("currentlist", val); //add to localStorage
});
and in your onload
var name = localStorage.getItem("currentlist"); //get from localStorage
$("#selector").html(name); //assign here
How can I clone the form ( address input) ? not working
how to fix this problem
I want to do in such a way as when the user deletes the input and then add it, it should be an active input again. https://jsfiddle.net/joio/95o0wyfy/29
$('.add_input').eq(0).click(function() {
form_a++;
var formhtml = $('#divform_a .form').eq(0).html().toString();
formhtml = formhtml.replace(/form_a/g, 'form_item'+form_a);
$('#divform_a').eq(0).append('<div class="form">' + formhtml + '</div>');
focus_map_location = jQuery('#divform_a .form:last .map_location');
$("#divform_a .form:last .address").removeAttr('id');
address_form = $("#address").parent();
$("#address").clone(true).prependTo(address_form).removeAttr('id');
address_name = $("#divform_a .form:last .address").attr('name');
$("#divform_a .form:last .address").remove();
$("#address").prependTo($("#divform_a .form:last")).attr('name',address_name).val('');
});
Your problem seems to be in these two lines
address_form = $("#address").parent();
$("#address").clone(true).prependTo(address_form).removeAttr('id');
Your code does not set id to the newly created input tags. Once you delete the original element with the id, the prepen stops working. Also, this seems a lot more complicated than it should be.
This is all that it takes to duplicate (and also to get the name tag working)
$('.add_input').click(function() {
form_a++;
var copiedForm = $('#divform_a .form').eq(0).clone();
copiedForm.attr('name', 'form_item'+form_a);
$('#divform_a').append(copiedForm);
});
Fiddle
EDIT:
Here's your fiddle with minimal changes. The following line at the end, reinstates the #address to the first input and now the copy function works as it should
$("#divform_a .form:first .address").attr('id', 'address');
I would still advise to take a look at the code in the first fiddle and try to clean up. Or at the very least, learn from it :)
Second Edit:
In your map fiddle, you're initializing autocomplete only for the first field. You should do something like this
$('.address').each(function(){
var autocomplete = new google.maps.places.Autocomplete(this);
autocomplete.bindTo('bounds', map);
autocomplete.setTypes([]);
google.maps.event.addListener(autocomplete,'place_changed', function() {
infowindow.close();
markerPoint.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
});
});
});
This will make an Autocomplete of both fields. The clone's automatically pick up the property.
I have the following fiddle:
http://jsfiddle.net/XpAk5/63/
The IDs increment appropriately. For the first instance. The issue is when I try to add a sport, while it duplicates, it doesn't duplicate correctly. The buttons to add are not creating themselves correctly. For instance, if I choose a sport, then fill in a position, and add another position, that's all fine (for the first instance). But when I click to add another sport, it shows 2 positions right away, and the buttons aren't duplicating correctly. I think the error is in my HTML, but not sure. Here is the JS I am using to duplicate the sport:
$('#addSport').click(function(){
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $('div.kpSports').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#kpSport').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
});
Hoping someone has an idea, perhaps I've just got my HTML elements in the wrong order? Thank you for your help! I'm hoping the fiddle is more helpful than just pasting a bunch of code here in the message.
The problem is in your clearCloneValues function. It doesn't differentiate between buttons and other for elements that you do want to clear.
Change it to:
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined && element.attr('type') !== 'button'){
element.val('');
}
}
As #PHPglue pointed out in the comments above, when new positions are added, they are incorrectly replicated (I'm assuming here) to the newly cloned for
There is a similar problem with the add years functionality.
A quick fix would be to initialize a variable with a clone of the original form fields:
var $template = $('div.kpSports').first().clone();
Then change your addSport handler to:
$('#addSport').click(function () {
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $template.clone();
…
});
However, there are no event bindings for the new buttons, so that functionality is still missing for any new set of form elements.
Demo fiddle
Using even a simple, naive string based templates the code can be simplified greatly. Linked is an untested fiddle that shows how it might be done using this approach.
Demo fiddle
The code was simplified to the following:
function getClone(idx) {
var $retVal = $(templates.sport.replace(/\{\{1\}\}/g, idx));
$retVal.find('.jsPositions').append(getItemClone(idx, 0));
$retVal.find('.advtrain').append(getTrainingClone(idx, 0));
return $retVal;
}
function getItemClone(setIdx, itemIdx) {
var retVal = itemTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, itemIdx);
return $(retVal);
}
function getTrainingClone(setIdx, trainingIdx) {
var retVal = trainingTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, trainingIdx);
return $(retVal);
}
$('#kpSportPlayed').on('click', '.jsAddPosition', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var itemIdx = $container.find('.item').length;
$container.find('.jsPositions').append(getItemClone(containerIdx, itemIdx));
});
$('#kpSportPlayed').on('click', '.jsAddTraining', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var trainIdx = $container.find('.advtrain > div').length;
$container.find('.advtrain').append(getTrainingClone(containerIdx, trainIdx));
});
$('#addSport').click(function () {
var idx = $('.kpSports').length;
var newItem = getClone(idx);
newItem.appendTo($('#kpSportPlayed'));
});