I have an array where if i delete a specific element it will remove it but later if i again remove another element the newly selected element will be deleted but previously deleted element will be present as shown in fig.
refer above picture at first i removed phone from a array and next i removed Account Disabled but in the second table the previously deleted element phone is still present
var selectedOpts = $('#lstBox1 option:selected');
var text = selectedOpts.val();
var colData = [];
this.firmData.forEach(function (dta) {
colData.push(dta.DisplayName);
})
const removeItem = value => colData.filter(item => item !== value)
console.table(removeItem(text))
console.log(text);
UPDATE
actual requirement
my requirement is i need to move data viceversa while moving i also want to remove it from array for now i can only append those values but i am not able to remove it from an array
1st column html
<div class="menu">
<select multiple="multiple" id='lstBox1' >
</select>
</div>
1st column JS code
self.firmData.forEach(function (data) {
$("#lstBox1").append($('<option class="items">').text(data.DisplayName).attr('value', data.DisplayName));
});
2nd column HTMl
<div class="menu">
<select multiple="multiple" id='lstBox2' >
</select>
</div>
2nd column JS code
self.data.forEach(function (data) {
$("#lstBox2").append($('<option class="items">').text(data.columnsexpo).attr('value', data.columnsexpo));
});
Button functions
"click #btnRight": function(e){
var selectedOpts = $('#lstBox1 option:selected');
var text = selectedOpts.val();
$('#lstBox2').append($(selectedOpts).clone())
this.data.push(columnsexpo: text);
}
"click #btnLeft": function(e){
var selectedOpts = $('#lstBox2 option:selected');
var text = selectedOpts.val();
$('#lstBox1').append($(selectedOpts).clone())
this.data.push(columnsexpo: text);
}
Not sure from the question what you're trying to do, but this should remove the item you want from the original array. Warning - may contain bugs / errors, however Array.prototype.splice removes items from an array.
var selectedOpts = $('#lstBox1 option:selected');
var text = selectedOpts.val();
var colData = [];
this.firmData.forEach(function (dta) {
colData.push(dta.DisplayName);
})
function findItem(item) {
return item == text;
}
colData.splice(colData.findIndex(findItem), 1);
console.table(colData)
console.log(text);
.filter don't remove item from array
To remove item in your array you can do
colData.splice(colData.indexOf(text), 1)
Live demo
var colData = ['a', 'b', 'c', 'd'];
const removeItem = value => {
let arr = colData.splice(colData.indexOf(value), 1);
return arr;
}
removeItem('a');
removeItem('d');
console.log(colData);
Related
I am trying to generate link on the button when multiple Checkbox is clicked based on the value. I have used the below link and it's working fine and I am able to generate link.
Create a dynamic link based on checkbox values
The issue is that when I select the checkbox for the first time it generates a link to /collections/all/blue+green but when I again select/deselect the different value its duplicates and ADDs the values with old Link → to collections/all/blue+green+blue+green
For Live Issue check on mobile View Click on filter on bottom => https://faaya-gifting.myshopify.com/collections/all
$("input[type=checkbox]").on("change", function() {
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val())
}
})
var vals = arr.join(",")
var str = "http://example.com/?subject=Products&checked=" + vals
console.log(str);
if (vals.length > 0) {
$('.link').html($('<a>', {
href: str,
text: str
}));
} else {
$('.link').html('');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<input type="checkbox" name="selected" value="Blue" class="products"> Blue<br>
<input type="checkbox" name="selected" value="Green" class="products"> Green<br>
<input type="checkbox" name="selected" value="Purple" class="products"> Purple
<br>
<span class="link"></span>
For Live Issue check on mobile View Click on filter on bottom => https://faaya-gifting.myshopify.com/collections/all
I see what's going on now. What's causing the duplicate is actually multiple checkboxes having the checked value.
If you run this code in your console, you should see that you have twice of the item checked as its length:
// Run this in your browser console
$('input[type=checkbox]:checked').length
For example, if I have Wood and Metal checked and clicked Apply, running the code above gives length of 4 instead of just 2. Meaning, you have a duplicate checkbox input for each filter hidden somewhere in your code. I have verified this.
As options, you can:
Try to remove the duplicate checkbox input – Best Option; or
Add class to narrow down your selector to just one of the checkbox input containers.
Here's a screenshare of what's going on: https://www.loom.com/share/2f7880ec3435427a8378050c7bf6a6ea
UPDATED 2020/06/09:
If there's actually no way to modify how your filters are displayed, or add classes to narrow things down, we can opt for an ad hoc solution which is to actually, just remove the duplicates:
// get all your values
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val().toLowerCase())
}
})
// removes duplicates
var set = new Set(arr)
// convert to array and join
var vals = [...set].join(",")
I am bit bad in jquery. Am I doing right?
Should I just add the script which I have written below
$("input[type=checkbox]").on("change", function() {
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val().toLowerCase())
}
})
// removes duplicates
var set = new Set(arr)
// convert to array and join
var vals = [...set].join(",")
var str = "http://example.com/?subject=Products&checked=" + vals
console.log(str);
if (vals.length > 0) {
$('.link').html($('<a>', {
href: str,
text: str
}));
} else {
$('.link').html('');
}
})
Am I right?
Or should I add any values on var set = new Set(arr) or var vals = [...set]
Thank you for you help Algef
I have coded some simple function which allow me to add order. I have also dynamically created the button which when called will remove the current html element which is a table row. Now, I am stuck with finding the current element index which I needed so I can use splice to remove it from the array.
const order = [];
const customer = {
name: '',
totalCups: 0
}
$('#btnAdd').click(function() {
debugger
var itemName = $('#customerName');
var itemTotalCups = $('#customerTotalCups');
customer.name = itemName.val();
customer.totalCups = itemTotalCups.val();
// Data structure Queue
order.push(Object.assign({}, customer));
// UI - HTML rendering - start
if (order.length === 1) {
// Create table column name
$('#AllOrders').append('<table id="tbl" class="table table-bordered"><tr><td>Customer</td><td>Cups</td><td></td></tr></table>');
}
var itemElement = `<tr><td>${itemName.val()}</td><td>${itemTotalCups.val()}</td><td><a class='del' href='#'>Cancel order</a></td></tr>`;
$('#tbl').append(itemElement);
// UI - HTML rendering - end
$('.del').click(function(e) {
e.stopImmediatePropagation();
// Delete order object
debugger
//var elm = $(this).parent().text().substr(0, $(this).parent().text().length-1);
console.log(elm);
console.log(order.indexOf(elm));
//order.splice(order.indexOf(elm),1);
//order.splice(2,1);
// Delete HTML element
$(this).parent().parent().remove();
})
// Reset textbox
itemName.val("");
itemTotalCups.val("");
// Optional Design
$('#ViewAllOrders').click();
debugger;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="customerName" type="text" />
<input id="customerTotalCups" type="number" />
<button id="btnAdd">Add</button>
<div id="AllOrders"></div>
I search for the solution but can't figure out the commented code below to find the element
//var elm = $(this).parent().text().substr(0, $(this).parent().text().length-1);
I am stuck inside $('.del').click event handler.
You can find the element in the order array by getting the index of the row where the clicked cancel button is.
To do so, you have to first get the current row. You can use the closest method:
var $row = $(this).closest('tr');
Now, you can get the index of the current row through the index method. You have to take into account that you have the tr for the header, you we need to substract one:
var index = $row.index() - 1;
Your final code should look like:
$('.del').click(function(e) {
e.stopImmediatePropagation();
var $row = $(this).closest('tr');
var index = $row.index() - 1;
order.splice(index, 1);
// Delete HTML element
$row.remove();
});
You can find the parent tr element and use that element to find the customer name and delete that node from DOM.
Couple of methods you want to try out:
.closest(): find the first match in the parent DOM hierarchy
https://api.jquery.com/closest
.filter(): filter an array based on some condition
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
So, basically you can find the closest tr node using closest and then find the customer name from within this tr's first td element.
Then, use filter on order to remove its instance from the order array.
Below is the changed code from the snippet:
$('.del').click(function(e) {
e.stopImmediatePropagation();
// Delete order object
var elm = $(this).closest('tr');
var nameToDelete = elm.find('td:first').text();
// filter out order
order = order.filter(item => item.name !== nameToDelete);
console.log('order now is = ', order);
// Delete HTML element
elm.remove();
});
More appropriately, learn about using HTML data-* Attributes along with id and class that could really ease up DOM manipulation. There are many samples online. Give that a try.
Cheers!
var order = [];
const customer = {
name: '',
totalCups: 0
};
$('#btnAdd').click(function() {
var itemName = $('#customerName');
var itemTotalCups = $('#customerTotalCups');
customer.name = itemName.val();
customer.totalCups = itemTotalCups.val();
// Data structure Queue
order.push(Object.assign({}, customer));
// UI - HTML rendering - start
if (order.length === 1) {
// Create table column name
$('#AllOrders').append('<table id="tbl" class="table table-bordered"><tr><td>Customer</td><td>Cups</td><td></td></tr></table>');
}
var itemElement = `<tr><td>${itemName.val()}</td><td>${itemTotalCups.val()}</td><td><a class='del' href='#'>Cancel order</a></td></tr>`;
$('#tbl').append(itemElement);
// UI - HTML rendering - end
$('.del').click(function(e) {
e.stopImmediatePropagation();
// Delete order object
var elm = $(this).closest('tr');
var nameToDelete = elm.find('td:first').text();
// filter out order
order = order.filter(item => item.name !== nameToDelete);
console.log('order now is = ', order);
// Delete HTML element
elm.remove();
});
// Reset textbox
itemName.val("");
itemTotalCups.val("");
// Optional Design
$('#ViewAllOrders').click();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="customerName" type="text" />
<input id="customerTotalCups" type="number" />
<button id="btnAdd">Add</button>
<div id="AllOrders"></div>
Am struggling hard to bind an array object with list of span values using watcher in Angularjs.
It is partially working, when i input span elements, an array automatically gets created for each span and when I remove any span element -> respective row from the existing array gets deleted and all the other rows gets realigned correctly(without disturbing the value and name).
The problem is when I remove a span element and reenter it using my input text, it is not getting added to my array. So, after removing one span element, and enter any new element - these new values are not getting appended to my array.
DemoCode fiddle link
What am I missing in my code?
How can I get reinserted spans to be appended to the existing array object without disturbing the values of leftover rows (name and values of array)?
Please note that values will get changed any time as per a chart.
This is the code am using:
<script>
function rdCtrl($scope) {
$scope.dataset_v1 = {};
$scope.dataset_wc = {};
$scope.$watch('dataset_wc', function (newVal) {
//alert('columns changed :: ' + JSON.stringify($scope.dataset_wc, null, 2));
$('#status').html(JSON.stringify($scope.dataset_wc));
}, true);
$(function () {
$('#tags input').on('focusout', function () {
var txt = this.value.replace(/[^a-zA-Z0-9\+\-\.\#]/g, ''); // allowed characters
if (txt) {
//alert(txt);
$(this).before('<span class="tag">' + txt.toLowerCase() + '</span>');
var div = $("#tags");
var spans = div.find("span");
spans.each(function (i, elem) { // loop over each spans
$scope.dataset_v1["d" + i] = { // add the key for each object results in "d0, d1..n"
id: i, // gives the id as "0,1,2.....n"
name: $(elem).text(), // push the text of the span in the loop
value: 3
}
});
$("#assign").click();
}
this.value = "";
}).on('keyup', function (e) {
// if: comma,enter (delimit more keyCodes with | pipe)
if (/(188|13)/.test(e.which)) $(this).focusout();
if ($('#tags span').length == 7) {
document.getElementById('inptags').style.display = 'none';
}
});
$('#tags').on('click', '.tag', function () {
var tagrm = this.innerHTML;
sk1 = $scope.dataset_wc;
removeparent(sk1);
filter($scope.dataset_v1, tagrm, 0);
$(this).remove();
document.getElementById('inptags').style.display = 'block';
$("#assign").click();
});
});
$scope.assign = function () {
$scope.dataset_wc = $scope.dataset_v1;
};
function filter(arr, m, i) {
if (i < arr.length) {
if (arr[i].name === m) {
arr.splice(i, 1);
arr.forEach(function (val, index) {
val.id = index
});
return arr
} else {
return filter(arr, m, i + 1)
}
} else {
return m + " not found in array"
}
}
function removeparent(d1)
{
dataset = d1;
d_sk = [];
Object.keys(dataset).forEach(function (key) {
// Get the value from the object
var value = dataset[key].value;
d_sk.push(dataset[key]);
});
$scope.dataset_v1 = d_sk;
}
}
</script>
Am giving another try, checking my luck on SO... I tried using another object to track the data while appending, but found difficult.
You should be using the scope as a way to bridge the full array and the tags. use ng-repeat to show the tags, and use the input model to push it into the main array that's showing the tags. I got it started for you here: http://jsfiddle.net/d5ah88mh/9/
function rdCtrl($scope){
$scope.dataset = [];
$scope.inputVal = "";
$scope.removeData = function(index){
$scope.dataset.splice(index, 1);
redoIndexes($scope.dataset);
}
$scope.addToData = function(){
$scope.dataset.push(
{"id": $scope.dataset.length+1,
"name": $scope.inputVal,
"value": 3}
);
$scope.inputVal = "";
redoIndexes($scope.dataset);
}
function redoIndexes(dataset){
for(i=0; i<dataset.length; i++){
$scope.dataset[i].id = i;
}
}
}
<div ng-app>
<div ng-controller="rdCtrl">
<div id="tags" style="border:none;width:370px;margin-left:300px;">
<span class="tag" style="padding:10px;background-color:#808080;margin-left:10px;margin-right:10px;" ng-repeat="data in dataset" id="4" ng-click="removeData($index)">{{data.name}}</span>
<div>
<input type="text" style="margin-left:-5px;" id="inptags" value="" placeholder="Add ur 5 main categories (enter ,)" ng-model="inputVal" />
<button type="submit" ng-click="addToData()">Submit</button>
<img src="../../../static/app/img/accept.png" ng-click="assign()" id="assign" style="cursor:pointer;display:none" />
</div>
</div>
<div id="status" style="margin-top:100px;"></div>
</div>
</div>
I have a multiselect Listbox and fetching the list of selected values using
$('[id*=ListBox]').click(function(){
var selectedItems = $(this).val();
var lastItem = $("[id*=ListBox] option:selected").last().val();
});
This returns me comma separated array of selected values. But the problem is the array is always sorted by values and not generated by order in which selected values were clicked.
3000 , 3005 , 3009 , 3011
But if I first click item with value 3011, then 3005 , then 3000 and last 3009 I want values in that order
3011 , 3005 ,3000 , 3009
How to get selected values in order in which they were clicked ?
EDIT
Getting the most recent value selected also solves my problem.
How to get most recent selected item ?
First, set an event that adds an integer to each listbox item whenever the user clicks. Store the integer in a hidden element somewhere on the page, or do something clever by setting a data-attribute on the element like this:
$(function() {
$("#ListBox").data("selected-index", 0);
});
$("#ListBox option").on("click", function() {
var currentSelectedIndex = $("#ListBox").data("selected-index");
$(this).data("counter", currentSelectedIndex++);
});
Then in order to get all those in the order they've been clicked:
function getOrderOfItems() {
var arrayOfSelected = new Array(),
// Use Math and .map() to get the highest data-counter:
counters = $("#ListBox option[data-counter]").map(function() {
return parseInt($(this).data("counter"), 10);
}).get();
var highestCounter = Math.max.apply(Math, counters);
// We have the highest counter, so use a for loop to select the selected options.
for (var i = 0; i < highestCounter; i++) {
arrayOfSelected.push($("#ListBox option[data-counter=" + i + "]"));
}
console.log(arrayOfSelected);
return arrayOfSelected;
}
Where arrayOfSelected contains the ListBox items in the order they were clicked.
Note, html from #PaulRoub 's Answer used , as no html appear at OP
If interpret Question correctly , try substituting change event for click event ; creating an array of selected values , utilize .slice(-2)[0] to view previously selected item .
$("#ListBox").data("prev", []).change(function(e) {
$(this).data().prev.push(this.value)
console.log($(this).data().prev.slice(-2)[0], // last selected item
$(this).data().prev) // array of selected items , in order selected
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<select id="ListBox" multiple>
<option value="3000">3000</option>
<option value="3001">3001</option>
<option value="3002">3002</option>
<option value="3003">3003</option>
<option value="3004">3004</option>
</select>
This is what worked for me . I had to take a global array and after each click compare selected items of listbox with elements in array . The difference between them gave me latest selected item .
$(document).ready(function () {
var arr = [];
$("[id*=listBox]").click(function () {
var lastItem = '';
var selArr = [];
var flag = 0;
selArr = $(this).val();
// alert(selArr);
if ( $(this).val()!=null) {
if ($(this).val().length > 2) {
lastItem = $(selArr).not(arr).get();
selArr = $.grep(selArr, function (value) {
return value != lastItem;
});
flag = 1;
//arr = [];
}
}
arr = selArr;
$(this).val(selArr);
if (flag == 1)
alert("Cannot select more than 2 items");
});
});
This question made me discover two strange things .
$("#Listbox option").click() doesn't fire on Internet explorer ( i used version 9 ) but
works fine on others . I don't know why option element in not
fetched in IE.
$(#Listbox).val() gives comma seprated list of selected values in
sorted order and not in order in which the items were selected. This
proved to be a major surprise and headache .
I've created a madlib style paragraph with multiple drop-down selections for synonyms of various words. Here's an example:
<p id="the-text">This is an example paragraph containing many
<select class="selector">
<option>selections</option>
<option>dropdown thingies</option>
<option>option choosers</option>
</select>that I would like to be able to
<select class="selector">
<option>click on</option>
<option>select</option>
<option>choose</option>
</select>and then know what the
<select class="selector">
<option>final</option>
<option>selected</option>
<option>variable</option>
</select>paragraph text is.
<select class="selector">
<option>It would be great</option>
<option>It would be nice</option>
<option>It'd be delightful</option>
</select>, and
<select class="selector">
<option>useful</option>
<option>helpful</option>
<option>interesting</option>
</select>to dynamically create paragraphs like this.</p>
<textarea id="text-area" rows="4" cols="110">This is where the text should appear...
</textarea>
Here is a live example: http://jsfiddle.net/T4guG/2/
Using jQuery and Javascript, I am trying to get the selected (and surrounding) text to appear in the text area.
It's kind of working, but there are two problems:
1) SOLVED: There was a problem with punctuation, but replacing:
if (element == "{") {
content_array[i] = foo[j];
j++;
}
with
if (element.indexOf('{') >= 0) {
content_array[i] = foo[j];
j++;
}
allows { to be detected consistently
2) SOLVED: you only can change the options once.
Is there a more elegant solution than what I have come up with? Here is the code:
function updateTextArea() {
//get all of the text selections, and put them in an array
var foo = [];
$('.selector :selected').each(function (i, selected) {
foo[i] = $(selected).text();
});
//get the paragraph content, and store it
var safe_content = $('#the-text').html();
//delete all the options
$('.selector').text('');
//get the text without the dropdown options
var content = $('#the-text').html();
//create a regex expression to detect the remaining drop-down code
var pattern = "<select class=\"selector\"></select>",
re = new RegExp(pattern, "g");
//replace all the drop-down selections with {
content = content.replace(re, "{");
//turn the content into an array
content_array = content.split(" ");
//go through the array, and if a element is {, go to "foo" and replace it with the selected option
var length = content_array.length,
element = null;
var j = 0;
for (var i = 0; i < length; i++) {
element = content_array[i];
if (element == "{") {
content_array[i] = foo[j];
j++;
}
}
//turn the array back into a paragraph
new_content = content_array.join(" ");
//replace the text with the origionanl text
$('#the-text').html(safe_content);
//put the new content into the text area
$('#text-area').val(new_content);
}
$(document).ready(function () {
updateTextArea();
});
$(".selector").change(function () {
updateTextArea();
});
You are splitting text based on " " (using space) and replacing element { with array value but text is. {, and contains comma i.e., {, is not equal to {. Add space after element {. This solves your first problem.
As you are removing and adding select options dynamically in function updateTextArea(). You have to use .on() to attach event handler for dynamically created elements.
Try:
$( document ).on("change",".selector",function() {
updateTextArea();
});
Instead of
$(".selector").change(function () {
updateTextArea();
});
DEMO FIDDLE