Removing duplicates from FOR statement in Javascript? - javascript

I have the following
var ahrefLength = $('a').length;
for (var i = 0; i < ahrefLength; i++) {
var ahrefUrl = $('a')[i].attr('href');
if(ahrefUrl != '') {
$('a')[i].text('Unique');
}
}
How can I fix this so that no duplicates of "href" appear ? At the moment, if 2 href are the same it fixes both ? i.e. I need to ensure that no duplicates

var list = {};
$('a[href]').text(function(i,text) {
var href = $(this).attr('href');
if( !(href in list) )
return list[href] = 'Unique';
else
; // what do you want to do with the duplicate?
});
To use a for statement:
var list = {};
var a_els = $('a[href]'); // Cache the DOM selection
var len = a_els.length;
for(var i = 0; i < len; i++) {
var a_i = a_els.eq(i);
var href = a_i.attr('href');
if( !(href in list) )
a_i.text(list[href] = 'Unique');
else
; // what do you want to do with the duplicate?
}

You can use an associative array (viz., an object) as a sort of "set" to keep track of what URLs you've already seen:
var ahrefLength = $('a').length;
var hrefsToSkip = { '': true };
for (var i = 0; i < ahrefLength; i++) {
var ahrefUrl = $('a')[i].attr('href');
if(! hrefsToSkip[ahrefUrl]) {
$('a')[i].text('Unique');
hrefsToSkip[ahrefUrl] = true;
}
}

var hrefIdx = {};
var href = null;
$('a').each(function(i, e) {
href = $(this).attr('href');
if ( href != '' && !hrefIdx[href]) {
$(this).text('Unique');
hrefIdx[href] = true;
}
});

Use jQuery slice:)
Demo: http://jsfiddle.net/mhNra/
Remove all duplicates starting from the end
$( "a" ).each( function() {
$( "a[href=" + $( this ).attr( "href" ) + "]" ).slice( 0, -1 ).remove()
});
Remove all duplicates starting from the first anchor
$( "a" ).each( function() {
var arr = $( "a[href=" + $( this ).attr( "href" ) + "]" );
arr.slice( 1, arr.length ).remove()
});

Related

How can I assign Id attribute to all the children of a contenteditable div on keyup?

I tried the following:
HTML:
<div contenteditable="true" id="editable"></div>
JS:
$('#editable').keyup(function() {
addID();
});
function addID()
{
$('#editable *').each(function() {
var t = GenerateID();
$(this).attr('id','id-' + t);
});
}
function GenerateID()
{
var str = 'abcdefghijklmnopqrstuvwxyz0123456789';
var alphabet = '',
genID = '';
while(genID.length < 5)
{
alphabet = str.charAt(Math.floor(Math.random() * str.length));
genID += alphabet;
}
return genID;
}
But on every keyup it keeps on changing the ID.
How can I just set the id once for all the elements while typing, and still keep it unique throughout the div ?
JSFiddle
LAST UPDATE:
Now I checked the code in your fiddle and I'm sure it works. The checking for uniqueness can probably be made into a function, but i'll leave that to you:
$('#editable').on( 'keyup', addID );
var count = 0; // this will absolutely ensure that ID will be unique
function addID(){
var previousIDs = [];
$('#editable *').each(function() {
count++;
var thisID = $(this).attr( 'id' );
// let's check if we have duplicates:
var index = 0, len = previousIDs.length, isDuplicate = false;
for( index = 0; index < len; index++ ){
if ( thisID === previousIDs[index] ) {
isDuplicate = true;
break;
}
}
// now change the ID if needed:
if ( isDuplicate || ! thisID ){
var t = GenerateID();
var newID = 'id-' + t + '-' + count;
$(this).attr('id', newID);
previousIDs.push( newID );
}else{
previousIDs.push( thisID );
}
});
}
Working Fiddle
Try this:
$('#editable').keyup(addID);
function addID() {
$('#editable *').each(function () {
var t = GenerateID();
var elem = $(this);
var attr = elem.attr('id');
if (!attr) {
elem.attr('id', 'id-' + t);
}
});
}
/**
* #return {string}
*/
function GenerateID() {
var str = 'abcdefghijklmnopqrstuvwxyz0123456789';
var alphabet = '',
genID = '';
while (genID.length < 5) {
alphabet = str.charAt(Math.floor(Math.random() * str.length));
genID += alphabet;
}
return genID;
}
Also consider that your random string generator may generate same string again.
Replace your code with following :
$('#editable *').each(function() {
if(!$(this).hasClass("idgenerated")){
console.log( $(this).attr('id') );
var t = GenerateID();
$(this).attr('id','id-' + t);
$(this).addClass("idgenerated");
console.log($(this).prop("tagName") + ' = ' + t);
}
});
Working fiddle

Loop through array to factorize javascript code

I have a javascript code that I need to repeat many times with just a slight change:
I need to take the function below and repeat it EXACTLY the same apart from changing info_throbber to video_throbber, then, to map_throbber, then picture_throbber and do tyhese changes only on 2 lines: line 2 and 9)
I don't want to just repeat theses dozens of line one after the other, even if it works. I would like to factorize it.
$(function() {
var $modal_types = $('select#game_info_throbber_modal_types') # FIRST INJECTION HERE
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=game_info_throbber][type=hidden]') # SECOND INJECTION HERE
;
$add_modal.click(function(e) {
e.preventDefault();
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
});
Using Loop through an array in JavaScript, here what I tried but it fails:
var i, s, myStringArray = [ "info_throbber", "video_throbbe", "map_throbber", "picture_throbber" ], len = myStringArray.length
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
// ... do stuff with s ...
$(function() {
var $modal_types = $('select#deal_' + s + '_modal_types')
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
;
$add_modal.click(function(e) {
e.preventDefault();
$(this).closest('li')
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
};
}
};
The problem is it seems to work but not fully as it did not append on both $add_modal nor does it allow to change values. I don't think it's necessary to understand deeply the complexe code above but the thing is it does not work while when I just put all of the 4 functions one after the other one (first for info_throbber, then video_throbber, and so on...), it works. So me creating an iteraiton through the array should be work.
thanks for yourt help,
You have a JavaScript scope issue. The function within the loop is only using the last i value provided for all iterations of that function. You need to pass the index into the function to make it work correctly.
See this stack question, JavaScript loop variable scope, for more information.
The simplest fix is to wrap your function like so
var i, myStringArray = [ "info_throbber", "video_throbber", "map_throbber", "picture_throbber" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
(function(index) {
var s = myStringArray[index];
// ... do stuff with s ...
$(function() {
var $modal_types = $('select#deal_' + s + '_modal_types')
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
;
$add_modal.click(function(e) {
e.preventDefault();
$(this).closest('li')
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
$submit.click(function(e) {
var components = JSON.stringify( collect_info_modals() )
;
$ol.find('ol.info_modal').remove();
$modal_types.remove();
$hidden_info_modals.val( components );
});
var modal_types_change = function() {
var $el = $(this)
, $li = $(this).closest('li')
, id = $(this).val()
, $components = $li.find('ol.components')
;
$components.remove();
get_modal_structure(id, $li.find('select') );
};
$modal_types.attr({ id: null, name: null });
$li.remove();
var create_info_modal = function($modal, modal_type_id) {
var $select = $modal_types.clone();
if($modal.find('select').length) { $select = $modal.find('select'); }
$select.val(modal_type_id);
$select.change(modal_types_change);
$modal.prepend($select);
$modal.append($add_modal);
$ol.append($modal);
};
var collect_info_modals = function() {
var $info_modals = $ol.find('ol.components')
, components = []
;
$.each($info_modals, function(_, $info_modal) {
$info_modal = $($info_modal);
var info_modal = {}
, $components = $info_modal.find('li.component input')
, modal_id = $info_modal.parent('li').find('select').val()
;
info_modal['modal_id'] = modal_id;
$.each($components, function(_, component) {
component = $(component);
key = component.attr('name');
val = component.val();
info_modal[key] = val;
component.remove();
});
$info_modal.parent('li').remove();
components.push(info_modal);
});
return components;
};
function get_modal_structure(id, $select) {
// Grab modal structure
var url = '/admin/modal_types/modal_structure?id='+id;
$.getJSON(url, function(modal_structure) {
var $ol = $('<ol class="components">');
modal_structure.forEach(function(component){
$ol.append(build(component));
});
$ol.insertAfter($select);
});
};
function build(component, value) {
value = value || '';
var text_maxlength = 300
, $li = $('<li class="component string input stringish" />')
, $label = $('<label>'+component+'</label>')
, $input = $('<input name="'+component+'" type="text" required="required" maxlength='+text_maxlength+' value="' + value + '"/>')
;
// validations
if(component.match(/^text/)) {
$input.attr('maxlength', text_maxlength);
}
$li
.append($label) // returns the LI NOT THE LABEL
.append($input);
return $li;
};
(function() {
var hidden_info_modals = ($hidden_info_modals.val().length) ? $hidden_info_modals.val() : '[]';
hidden_info_modals = JSON.parse( hidden_info_modals );
hidden_info_modals.forEach(function(info_modal) {
var modal_type_id
, $info_modal = $li.clone(true)
, $ol = $('<ol class="components">');
;
modal_type_id = info_modal['modal_id'];
delete info_modal['modal_id'];
for (var key in info_modal) {
$ol.append(build(key, info_modal[key]));
}
$info_modal.append($ol)
$info_modal.append($remove_modal.clone(true))
create_info_modal($info_modal, modal_type_id);
});
})();
create_info_modal($li.clone(true));
});
})(i);
}
Also, you should remove if (i in myStringArray) as that is only needed when you do a foreach loop over the attributes of an object, not when you are looping over the indexes of an array.

escaped URL parameters statements if else switch

There is a little problem with this code:
function getParameters() {
var searchString = document.getElementById('input1').value,
params = searchString.split("&"),
hash = {};
if (searchString == "") return {};
for (var i = 0; i < params.length; i++) {
var val = params[i].split("=");
hash[unescape(val[0])] = unescape(val[1]);
}
console.log(hash);
//return hash;
if(val[0] == "class"){ //alert(val[1]);
$.each(hash, function( attribute, value ) {
test_div.setAttribute(attribute,value);
});
}
else if(val[0] == "color"){ //alert(val[1]);
$.each(hash, function( attribute, value ) {
test_div.style[attribute]=value;
});
}
monitor_test_div.innerText = ccc.innerHTML;
}
Depending by the order in which the parameters are inserted, they are repeated or dont work...
style a div using escaped URL parameters
Demo: JSFiddle 1
Demo: JSFiddle 2
I would like to obtain this:
Example 1:
input:
opacity=0&src=link1&color=red&color=green&src=link2&height=200
output:
<div src="link2" style="color: green;"></div>
Example 2:
input:
src=link1&color=red or color=red&src=link1
output:
<div src="link1" style="color: red;"></div>
in your line
if(val[0] == "class")
you are only checking the first element in your val array.
what you would want to do, is iterate through all the hash objects and simply check the attribute like this:
function getParameters() {
var searchString = document.getElementById('input1').value,
params = searchString.split("&"),
hash = {};
if (searchString == "") return {};
for (var i = 0; i < params.length; i++) {
var val = params[i].split("=");
hash[unescape(val[0])] = unescape(val[1]);
}
console.log(hash);
//return hash;
$.each(hash, function( attribute, value ) {
if(attribute=="color"){
test_div.style[attribute]=value;
}
else if(attribute=="src"){
alert(attribute);
test_div.setAttribute(attribute,value);
}
});
}
here is a working FIDDLE
Maybe you want something like this:
var test_div = $('#test_divs_id');
for (var i = 0; i < params.length; i++) {
var val = params[i].split("=");
var key = unescape(val[0]);
var val = unescape(val[1]);
switch(key) {
case 'class': // treat 'class' key by ...
test_div.addClass(val); // ... adding the value as a class
break;
case 'src': // treat 'src' key,
case 'href': // treat 'href' key, maybe more ...
test_div.attr(key, val); //... by adding as an attribute with value
break;
default: // all other keys...
test_div.css(key, val); // ... are assumed css style names with value
break;
}
EDIT: Extended the switch with the examples + possibly more attributes

How do i declare this and set values later? (javascript)

This is the code I have and it is not working. I dunno how to declare this
var input = {
container: '.slide_container',
container_all: '.slide_show',
slides: []
};
var $slides = $('.slide_show .slide');
var l = $slides.length;
for( var i = 0; i < l; i++ ) {
input.slides[i].el = '#' + $slides.eq(i).attr('id');
if( i === 0 ) {
input.slides[i].weight = 1;
} else {
input.slides[i].weight = 0;
}
}
When it gets to
input.slides[i].el = '#' + $slides.eq(i).attr('id');
it says the input.slides[i].el is undefined. Can someone let me know the correct way to declare the empty slides?
You need to create your object first. Something like:
input.slides[i] = { el: '#' + $slides.eq(i).attr('id'), weight: 0 };
You also might want to consider using push to add to your array.
input.slides.push({ el: '#' + $slides.eq(i).attr('id'), weight: 0 }); //Add new object to the array
You should initialize input.slides[i] before assign something to its attribute.
for( var i = 0; i < l; i++ ) {
input.slides[i] = {};
input.slides[i].el = '#' + $slides.eq(i).attr('id');
if( i === 0 ) {
input.slides[i].weight = 1;
} else {
input.slides[i].weight = 0;
}
}

How to parse input[] values and put them into a Javascript Array

Let's say i have this:
<form id='foo'>
<input name='bar[name]' />
<input name='bar[age]' />
</form>
How can i get the values of array inputs within the form foo and put them into an associative array/object like this:
var result = {bar:{name:'blah',age:21}};
P.S. I don't want to use any frameworks for this.
I needed to do this myself and after finding this question I didn't like any of the answers: I don't like regex and the others are limited.
You can get the data variable many ways. I'll be using jQuery's serializeArray method when I implement this.
function parseInputs(data) {
var ret = {};
retloop:
for (var input in data) {
var val = data[input];
var parts = input.split('[');
var last = ret;
for (var i in parts) {
var part = parts[i];
if (part.substr(-1) == ']') {
part = part.substr(0, part.length - 1);
}
if (i == parts.length - 1) {
last[part] = val;
continue retloop;
} else if (!last.hasOwnProperty(part)) {
last[part] = {};
}
last = last[part];
}
}
return ret;
}
var data = {
"nom": "123",
"items[install][item_id_4]": "4",
"items[install][item_id_5]": "16",
"items[options][takeover]": "yes"
};
var out = parseInputs(data);
console.log('\n***Moment of truth:\n');
console.log(out);
You can map the elements to an object like this.
function putIntoAssociativeArray() {
var
form = document.getElementById("foo"),
inputs = form.getElementsByTagName("input"),
input,
result = {};
for (var idx = 0; idx < inputs.length; ++idx) {
input = inputs[idx];
if (input.type == "text") {
result[input.name] = input.value;
}
}
return result;
}
var form = document.getElementById( 'foo' );
var inputs = form.getElementsByTagName( "input" );
var regex = /(.+?)\[(.+?)\]/;
var result = {};
for( var i = 0; i < inputs.length; ++i ) {
var res = regex.exec( inputs[i].name );
if( res !== null ) {
if( typeof result[ res[1] ] == 'undefined' ) result[ res[1] ] = {};
result[ res[1] ][ res[2] ] = inputs[i].value;
}
}
var inputs = document.getElementsByTagName('input');
var field_name, value, matches, result = {};
for (var i = 0; i < inputs.length; i++) {
field_name = inputs[i].name;
value = inputs[i].value;
matches = field_name.match(/(.*?)\[(.*)\]/);
if (!results[matches[0]]) {
results[matches[0]] = {};
}
results[matches[0]][matches[1]] = value;
}
This will get you the elements:
var result = {};
var elements = document.forms.foo.getElementsByTagName("input");
for(var i = 0; i < elements.length; i++)
{
/* do whatever you need to do with each input */
}

Categories

Resources