Control duplicate entries with angular.js - javascript

I’m using angular.js to get some form data from some input fields. I need to build a feature that prevents a user from entering duplicate fields. So if a user entered duplicate fields I need alert the user with a alert box and than remove the duplicate. I know how to do this with jQuery, look at the code below. What is the most efficient way to achieve this with angular.js? Any help is greatly appreciated, I have template fiddle here to make it easier.
/** Handle Duplicate Barcodes **/
$(".alldifferent").on('keyup paste',function(){
var $this = $(this);
keyupDelay(function() {
var val = $this.val();
$this.attr('value', val);
if (val != '') {
var $dupes = $('input[value="' + val + '"]:gt(0)').val('');
if ($dupes.length > 0) alert('Error: Duplicates barcodes are not allowed!');
}
}, 300);
});
var keyupDelay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();

Try ng-blur as a blur event fires when an element has lost focus.
If you can know the index at which the duplicate entry is being entered you can filter that item in the array and clear it.
$scope.check = function(val, index){
if(val !== '') {
for(var i = 0; i < $scope.num.length; i++ ){
var itm = $scope.num[i].text;
if(itm == val && i != index) {
$scope.num[index].text = '';
alert('Error: Duplicates barcodes are not allowed!');
break;
}
}
}
}
Working Plunker

Related

How to make other JQuery run when a separate function runs?

I have the JS code below which filters based on checkboxes being checked or not (I don't think you need to see all the HTML because my question is rather simple/general, I think). All this code works fine, but I added a new function at the bottom (I noted it in the code) that simply has an uncheck all button for one of the sets of checkboxes (because there are like 30 checkboxes and I don't want the user to have to uncheck them all manually).
Anyway, the new script works properly too, except that the overall unrelated script that compares all checkboxes needs to run each time the new Uncheck All/Check All button is clicked.
Is there a simple way to make sure all the other JS runs when this new script is run?
I could be wrong, but I think I just need to somehow trigger this function inside the NEW FUNCTION:
$checkboxes.on('change', function() {
but am not sure how to do that.
ALL JS:
<script>
$(window).load(function(){
Array.prototype.indexOfAny = function(array) {
return this.findIndex(function(v) {
return array.indexOf(v) != -1;
});
}
Array.prototype.containsAny = function(array) {
return this.indexOfAny(array) != -1;
}
function getAllChecked() {
// build a multidimensional array of checked values, organized by type
var values = [];
var $checked = $checkboxes.filter(':checked');
$checked.each(function() {
var $check = $(this);
var type = $check.data('type');
var value = $check.data('value');
if (typeof values[type] !== "object") {
values[type] = [];
}
values[type].push(value);
});
return values;
}
function evaluateReseller($reseller, checkedValues) {
// Evaluate a selected reseller against checked values.
// Determine whether at least one of the reseller's attributes for
// each type is found in the checked values.
var data = $reseller.data();
var found = false;
$.each(data, function(prop, values) {
values = values.split(',').map(function(value) {
return value.trim();
});
found = prop in checkedValues && values.containsAny(checkedValues[prop]);
if (!found) {
return false;
}
});
return found;
}
var $checkboxes = $('[type="checkbox"]');
var $resellers = $('.Row');
$checkboxes.on('change', function() {
// get all checked values.
var checkedValues = getAllChecked();
// compare each resellers attributes to the checked values.
$resellers.each(function(k, reseller) {
var $reseller = $(reseller);
var found = evaluateReseller($reseller, checkedValues);
// if at least one value of each type is checked, show this reseller.
// otherwise, hide it.
if (found) {
$reseller.show();
} else {
$reseller.hide();
}
});
});
//NEW FUNCTION for "UNCHECK ALL" Button
$(function() {
$(document).on('click', '#checkAll', function() {
if ($(this).val() == 'Check All') {
$('input.country').prop('checked', true);
$(this).val('Uncheck All');
} else {
$('input.country').prop('checked', false);
$(this).val('Check All');
}
});
});
});
New button HTML for the new UNCHECK portion:
<input id="checkAll" type="button" value="Uncheck All">
I kept researching and discovered the trigger() function to handle this.
http://api.jquery.com/trigger/

Select2: Multiple select elements constrained

I am trying to achieve something and I can't find/decide what is the best way to do it, so i'm going to ask if somebody did this before or if select2 has something built in in order to achieve what I want.
Heres the thing: I have a number of select (multiple) elements in my DOM, lets say 5, all share the same options, but, If one of the selects has an option selected, I want the others to hide/remove/avoid being selected, I would like to constrain all selects in order to avoid having the same value selected in 2 different selects. I am not asking for a full code solution, I just need to know if someone already did it (if yes, would be nice to get it shared in order for future developers that stumble upon this can see the solution), or if select2 has the functionallity.
What I have done so far is:
$('.constrainedSelect').each(function(i, select) {
var selectedValue = $(select).select2("val");
var options = $('#allOptions').find('option').clone();
if (selectedValue.length !== 0) {
options.each(function(i, option) {
if($(select).find('option[value="' + $(option).val() + '"]').length !== 1) {
$(select).append(option);
}
});
} else {
options.push($("<option />", {value: e.choice.id.trim(), text: e.choice.text.trim()})[0]);
$(select).html(options);
}
});
But thats just a concept and its really buggy.
The version of select2 i'm using (and need to use, no time to change it in production yet) is Version: 3.5.2 Timestamp: Sat Nov 1 14:43:36 EDT 2014
Thanks in advance!
I have found a nice way to do this, if anyone was wondering how, I think this is a good approach but I would like to see comments and if somebody wants to improve my answer, feel free to copy the code and paste it in a separate answer, if the approach gets better I will accept that answer. Thanks guys for the help.
var $selects = $(".constrainedSelects");
$selects.on('change', function(e) {
var selectedValues = $(this).select2('val');
for (var i = 0; i < selectedValues.length; i++) {
$selects.not(this).find("option[value='" + selectedValues[i] + "']").attr('disabled', true);
}
});
$selects.on('select2-removed', function(e) {
$selects.find("option[value='" + e.val + "']").attr('disabled', false);
});
Here is a fiddle to show the result: http://jsfiddle.net/rv38f0v6/
Please See if this helps! this is a jquery validation method to avoid same values in different select boxes.
$.validator.addMethod("valOption", function(value, element) {
var curValue,
allElems,
counter,
totalCount = 0;
curValue = value;
allElems = $('#myPage select');
for (counter = 0; counter < allElems.length; counter = counter + 1) {
if (curValue === allElems.eq(counter).val()) {
totalCount = totalCount + 1;
}
}
if (totalCount === 1) {
return this.optional(element) || (true);
} else {
return (false);
}
}, "Please select different option");
$(document).on('change', '.constrainedSelect', function() {
var changedSelect = $(this);
$(".constrainedSelect").not(changedSelect).select2("val", "").select2("enable", false)
});
I think something like this event listener would take care of it. It makes sure the val of all the others are empty and then disables them so they cannot be selected from.
How about this instead:
Working Fiddle
//setup trackign array and block duplicate selections
var selectedIds = [];
$(document).on('select2-selecting', '.constrainedSelect', function(event) {
var idx = $.inArray(event.val, selectedIds);
if(idx === -1) {
selectedIds.push(event.val);
} else {
event.preventDefault();
}
});
//remove selected item from our tracking array
$(document).on('select2-removed', '.constrainedSelect', function(event) {
var idx = $.inArray(event.val, selectedIds);
selectedIds.splice(idx,1);
});

onclick clone shipping address fields values to billing address fields values

Hi i have this javascript code
copyAddress : function(swapMode, container){
var thisInstance = this;
var addressMapping = this.addressFieldsMappingInModule;
if(swapMode == "false"){
for(var key in addressMapping) {
var fromElement = container.find('[name="'+key+'"]');
var toElement = container.find('[name="'+addressMapping[key]+'"]');
toElement.val(fromElement.val());
}
} else if(swapMode){
var swappedArray = thisInstance.swapObject(addressMapping);
for(var key in swappedArray) {
var fromElement = container.find('[name="'+key+'"]');
var toElement = container.find('[name="'+swappedArray[key]+'"]');
toElement.val(fromElement.val());
}
this code working fine if elements are input text fields
but not for select dropdown elements
I my form I have only input text and select fields and i want to modyfy this code to work with select fields too
I made a change to code like this
if(!(fromElement).is("select")) {
toElement.val(fromElement.val());
}else{
var $options = $(fromElement+" > option").clone();
toElement.append($options);
}
but without success.
Maybe anyone can help me please?
Thanks!
This will do your work.
I have added a check that if the element to copy is Select or not. In case of select element all the options of From element will be copied and appended to To element.
Try it and let me in case of any issue.
copyAddress : function(swapMode, container){
var thisInstance = this;
var addressMapping = this.addressFieldsMappingInModule;
if(swapMode == "false"){
for(var key in addressMapping) {
var fromElement = container.find('[name="'+key+'"]');
var toElement = container.find('[name="'+addressMapping[key]+'"]');
if(fromElement[0].tagName == "Select")
{
toElement.find('option').remove();
toElement.append(fromElement.find('option'));
}
toElement.val(fromElement.val());
}
} else if(swapMode){
var swappedArray = thisInstance.swapObject(addressMapping);
for(var key in swappedArray) {
var fromElement = container.find('[name="'+key+'"]');
var toElement = container.find('[name="'+swappedArray[key]+'"]');
if(fromElement[0].tagName == "Select")
{
toElement.find('option').remove();
toElement.append(fromElement.find('option'));
}
toElement.val(fromElement.val());
}
The solution was toElement.val(fromElement.val()).trigger("liszt:updated"); this work for all elements in form that use chosen.js

get index of input element in javascript

If I have 3 input boxes on a web page and the user clicks the second input, I need to get the input index, the position of the input on the page. I need it in pure javascript. This is what I have so far but it doesn't work...
document.querySelector('html').onclick = function (e) {
log(e);
}
function log(obj) {
var nodeName = obj.target.nodeName
var idx = nodeName.length
console.log(nodeName, idx);
}
Any help would be appreciated!
Pure javascript:
function getIndexFromSet(set, elm){
var setArr = [].slice.call(set);
for( var i in setArr )
if( setArr[i] == elm )
return i;
}
The above function can be used like so:
function checkInputFocus(e){
if(e.target && e.target.nodeName == 'input' )
index = getIndexFromSet(inputs, e.target);
}
var inputs = document.querySelectorAll('input');
document.addEventListener("click", checkInputFocus);
using jQuery, if you run this on this page (in your console)
var inputs = $('input'); // get all input elements on the page
inputs.index( $('#save-pinned-sites-btn') ); // find the index of spesific one
you will get a number representing the index of an $('#save-pinned-sites-btn') element
Inline:
<input onclick="for(i=0;i<this.parentNode.getElementsByTagName('input').length;i++){if(this==this.parentNode.getElementsByTagName('input')[i]){alert(i);}}">
Or change that to
onclick="show_index(this)"
And Add:
function show_index(which) {
for(i=0;i<which.parentNode.getElementsByTagName('input').length;i++){
if(which==which.parentNode.getElementsByTagName('input')[i]){
alert(i);
}}

Navigating (traversing) with jquery

I have a simple jq code to create autosuggestions (google like). It works fine and I just want to add keyboard events handlers. However I have some problems with it. When I want to choose the next suggestion with event 40 (arrow down) it get all the suggestions instead of just the next one. Any idea how to fix it?
$(document).ready(function(){
var people = ['Peter Bishop', 'Nicholas Brody', 'Gregory House', 'Hank Lawson', 'Tyrion Lannister', 'Nucky Thompson'];
var cache = {};
var drew = false;
$("#search").on("keyup", function(event){
var query = $("#search").val()
if($("#search").val().length){
//Check if we've searched for this term before
if(query in cache){
results = cache[query];
}
else{
//Case insensitive search for our people array
var results = $.grep(people, function(item){
return item.search(RegExp(query, "i")) != -1;
});
//Add results to cache
cache[query] = results;
}
//First search
if(drew == false){
//Create list for results
$("#search").after('<div id="res"></div>');
//Prevent redrawing/binding of list
drew = true;
//Bind click event to list elements in results
$("#res").on("click", "div", function(){
$("#search").val($(this).text());
$("#res").empty();
});
$("#search" ).keydown(function( event ) {
if ( event.which == 40 ) {
$("#search").val($(".suggestions").next().text());
}
});
}
//Clear old results
else{
$("#res").empty();
}
//Add results to the list
for(term in results){
$("#res").append("<div class = 'sugestions'>" + results[term] + "</div>");
}
}
//Handle backspace/delete so results don't remain
else if(drew){
$("#res").empty();
}
});
});
<input id="search" type="text">
You need to keep track of the currently selected suggestion. Simplest approach is probably to add/remove a className, something like this :
if(drew == false){
//Prevent redrawing/binding of list
drew = true;
//Create list for results, and bind click event to list elements in results
var $res = $('<div id="res"></div>').insertAfter("#search")
.on("click", "div", function() {
$(".suggestions").removeClass('selected');
$("#search").val($(this).addClass('selected').text());
$("#res").empty();
});
var $search = $("#search").keydown(function(event) {
var $suggestions, $selected, index;
if (event.which == 40) {
$suggestions = $(".suggestions");
$selected = $suggestions.find('.selected').eq(0);//.eq(0) shouldn't be necessary, but just in case ...
if($selected.length) {
index = ($selected.index() + 1) % $suggestions.length;//assuming the suggestions are siblings
} else {
index = 0;
}
$(".suggestions").removeClass('selected');
$search.val($(".selected").eq(index).addClass('selected').text());
}
});
} else { //Clear old results
$("#res").empty();
}
Not sure if that's 100% correct as I've had to make a couple of assumptions, but the approach should be about right.

Categories