Dynamically create javascript values with given data-attributes? - javascript

I have build an dynamic ajax function that saves data-xxx-values of elements to process the data. However I want to shorten this code which takes values depending on the ajax-request I want to process:
var data_form = $(element).attr('data-form');
var data_index = $(element).attr('data-index');
var data_hide_error = $(element).data('hide-error');
var data_disable_blur = $(element).data('disable-blur');
var data_hide_success = $(element).data('hide-success');
in a way that I only have one or two lines of code where I check which data-values are given in the element and if there is one data-value, I want to create a variable with that exact name.
For example: I click on this anchor send and my function would create the variables var data_index = 1; and var data_form = '#registerForm'; automatically.
How could I achieve this?

Perhaps you meant this: Using .data() will return all data-attributes in one object to use in the function that you call
$(function() {
$("a").on("click",function(e) {
e.preventDefault();
console.log($(this).data())
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
send

Related

How to create an array or object of variables by looking them in the DOM?

I am generating some JS variables on a Twig template and I am prefixing them with a dynamic value. For example:
<script type="text/javascript">
quoteGridId = 'grid_quote';
</script>
<script type="text/javascript">
quoteContactGridId = 'grid_quote_contact';
</script>
<script type="text/javascript">
archiveGridId = 'grid_archive';
</script>
I need to be able to use them in a Javascript file included after the page loads. How can I create an array of values containing all the *GridId vars?
I would like to be able to use the following on the script:
[
'quoteGridId' => 'grid_quote',
'quoteContactGridId' => 'grid_quote_contact',
'archiveGridId' => 'grid_archive',
]
UPDATE:
Let's try to get my problem clear for those ones opened to help. Currently I am working on a legacy system. Such system had a grid generating a gridId value and at the end a JS file was included and such file was using the var gridId to perform several things.
Now I need to replicate more than one grid on the same page and that becomes a problem since two grids are generating the same var name:
gridId = 'something';
gridId = 'something1';
When the script try to reach the gridId var is getting always the latest one (something1) and therefore no actions are being taken on the first grid.
My solution was to prefix the name to each gridId resulting on what I've as OP. Ex:
somethingGridId = 'something';
something1GridId = 'something1';
What I am trying to find is a way to re-use the main JS file by passing those dynamic gridIds but I can't find a way to get this to work.
The only solution I've in mind is to create the same file per grid and then change the value of gridId to the name of the ID to be used ....
I am open to ideas, any?
You can search the window variables with regex expressions (regular expression expressions?) i.e./.+GridId/ matches any word or variable that ends in GridId you can then iterate over them as you wish.
Example:
var pattern = /.+GridId/;
GridIds = []
for (var varName in window) {
if (pattern.test(varName)) {
GridIds.push({varName:window[varName]})
}
}
console.log(GridIds);
<script type="text/javascript">
quoteGridId = 'grid_quote';
</script>
<script type="text/javascript">
quoteContactGridId = 'grid_quote_contact';
</script>
<script type="text/javascript">
archiveGridId = 'grid_archive';
</script>
Hope this helps!
Instead of assigning quoteGridId = 'grid_quote', why don't you create a top level object and then assigning each var as a key-val pair, like:
var gridData = {}
gridData.quoteGridId = 'grid_quote'
gridData.quoteContactGridId = 'grid_quote_contact';
/* etc assignments */
//Access your data points like so in a loop, if you choose
Object.keys(gridData).forEach(key => {
const val = gridData[key]
//User `key`, and `val` however you'd like
})
i think you have you use List.
each time you push you value to the list like that :
var myList = [];
myList.push('something');
myList.push('something1');
now you cann access to all of them like that :
console.log(myList[0]);
console.log(myList[1]);
or just last :
console.log(myList[myList.length - 1])

Pass array to Javascript onClick function while adding links into a string?

I know the question sounds strange, but it's really very simple. I have the following function which isn't working:
function start40Counter(counter40_set){console.log(counter40_set);
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
cont += "<a class='suitpick' onClick='pickSuit(counter40_set);'><img src='"+base+"images/someimg.png' title='Odaberi' /></a>";
});
$('#game40_picks').html(cont);
}
counter40_set is [10, 3, ["H", "S"]]. The part of the function that fails is the part this:
onClick='pickSuit(counter40_set);'
It says that counter40_set is not defined. I understand that. This wouldn't even work if counter40_set was a simple string instead of an array. If I try onClick='pickSuit("+counter40_set+");' I get a different error, saying H is not defined. I get this too, the array is rendered and JS doesn't know what H and S are.
I also tried passing the array elements (counter40_set[0] etc) individually but it still fails with the last element (["H", "S"]).
So, how do I pass this data to the onClick function in this case? There must be a more elegant way than concatenating the whole thing into a string and passing that to the function?
Btw, this is a simplified version. What I should really be passing in every iteration is [suit, counter40_set] so that each link chooses a different suit. I'm asking the simplified question because that will be enough to send me down the right path.
It cannot work,because the context is lost and thus "counter40_set" is not set.
To fix it simply use jquery for the onlick as well:
$('#game40_picks').empty(); // get rid of everything
$.each(suits, function (num, suit) {
var line = $("<a class='suitpick'><img src='"+base+"images/"+cardsuits[suit].img+"' title='Odaberi "+cardsuits[suit].name+"' /></a>");
line.click(function(ev){
ev.preventDefault(); // prevent default click handler on "a"
pickSuit(counter40_set);
});
$('#game40_picks').append(line);
});
this way the "counter40_set" is available for the click function.
You shouldn't use the onClick HTML attribute. Also, using DOM functions to build nodes saves the time it takes jQuery to parse strings, but basically the method below is to create the element and attach a click event listener and then append it to the specified element.
function start40Counter(event){console.log(event.data.counter40_set);
var counter40_set = event.data.counter40_set;
var gid = counter40_set[0];
var seat = counter40_set[1];
var suits = counter40_set[2];
var cont = "";
$.each(suits, function (num, suit) {
var link = document.createElement('a');
link.className = 'suitpick';
$(link).on('click', {counter40_set: counter40_set}, start40Counter);
var img = document.createElement('img');
img.src= base + "images/" + cardsuits[suit].img;
img.title = 'Odaberi ' + cardsuits[suit].name;
link.appendChild(img);
$('#game40_picks').append(link);
});
}
Not tested but it might work out of the box.

Page with multiple dropdown filters

I have a page which uses dropdowns to filter a listing. I have over 10 filters now and each of the change function, I am calling an AJAX request and passing corresponding variables to the PHP function. Like this :
$("#categories").change(function() {
uri = "myurl" ;
var status=$("#statusfilter").val();
var category=$("#categories").val();
var network=$("#networksfilter").val();
var prod_type = $("#prodtypefilter").val();
loadData(uri,category,status,network,prod_type);
});
and in loadData() I have the following code :
function loadData(uri,category,status,network,prod_type){
url + = category+"/"+status+"/"+network+"/"+prod_type;
$('#userdata').load(url);
}
Here I have given only 4 filters only, but it is actually 10 and may increase.Anyway this is working fine. But the problem is that as I increase the filters, I need to write this same for every dropdown change function. Is there any better approach to optimze the code and so I don't need to load a bunch of JS ?
Rename your filter elements' IDs to start with same word, for example "filter_". Then get all of them at once:
$('select[id^="filter_"]').change(function() {
var uri = "myurl";
var filters = new Array();
$('select[id^="filter_"]').map(function () {
filters[$(this).name()] = $(this).val(); // not tested, just an idea
});
loadData(uri,filters);
});
.map() iterates over its elements, invoking a function on each of them and recording the selected option value in the array.
You can use .each() if it's more intuitive from .map() for you:
$.each('select[id^="filter_"]', function() {
filters[$(this).name()] = $(this).val(); // not tested, just an idea
});
Note: It's a good idea to use associative array as #Tony noticed below to be sure which filter is for which database table attribute in your server side script.
You will need to write some code in any cases, but you can reduce it, for example like this:
$("#categories").change(function() {
uri = "myurl";
var filters = {
status: $("#statusfilter").val(),
category: $("#categories").val(),
network: $("#networksfilter").val(),
prod_type: $("#prodtypefilter").val()
}; // order is important
loadData(filters );
});
loadData(filters) {
var url = '';
for (var filterName in filters)
url += '/' + (filters[filterName] || 'any'); // here some def value needed
url = url.substring(1); // cut first slash
$('#userdata').load(url);
}
EDIT
Or even like this:
loadData(filters) {
var url = Object.keys(filters).map(function(el) {
return filters[el] || 'any';
}).join('/');
$('#userdata').load(url);
}

Select multiple jQuery objects with .add()

Does the .add() method allow selecting multiple objects in one go instead of adding one at a time?
one.add(two).add(three).add(four).on("click", function() { });
The following variables are set in the way they do because each carries a different function.
var one = $("#1");
var two = $("#2");
var three = $("#3");
var four = $("#4");
But what if I want to add an extra function that applies to all of these elements? Do I have to add them one by one?
I know you can select them all using $("#1,#2,#3,#4"), but I just want to make use of the above variables.
I'd prefer this array approach, purely for readability...
$([one, two, three, four]).each(function() {
// your function here
});
You cannot add multiple objects in one go, for example:
var groupThree = one.add(three, five); // will not work as expected
You could cache the added objects so that you only have to do the add one time - http://jsfiddle.net/X5432/
var one = $("#1");
var two = $("#2");
var three = $("#3");
var four = $("#4");
var five = $("#5");
var groupOne = one.add(two).add(three).add(four);
var groupTwo = groupOne.add(five);
$('#first').click(function(e){
e.preventDefault();
groupOne.css({'background': '#00FF00'});
});
$('#second').click(function(e){
e.preventDefault();
groupTwo.css({'background': '#FF0000'});
});
But I like the array method better, this is just a different way of thinking about it.
You could put them into an array like this
var k = [one,two,three,four]
$.each(k,function(){
$(this).click(function(){
//Function here
});
});

Looping over elements in jQuery

I want to loop over the elements of an HTML form, and store the values of the <input> fields in an object. The following code doesn't work, though:
function config() {
$("#frmMain").children().map(function() {
var child = $("this");
if (child.is(":checkbox"))
this[child.attr("name")] = child.attr("checked");
if (child.is(":radio, checked"))
this[child.attr("name")] = child.val();
if (child.is(":text"))
this[child.attr("name")] = child.val();
return null;
});
Neither does the following (inspired by jobscry's answer):
function config() {
$("#frmMain").children().each(function() {
var child = $("this");
alert(child.length);
if (child.is(":checkbox")) {
this[child.attr("name")] = child.attr("checked");
}
if (child.is(":radio, checked"))
this[child.attr("name")] = child.val();
if (child.is(":text"))
this[child.attr("name")] = child.val();
});
}
The alert always shows that child.length == 0. Manually selecting the elements works:
>>> $("#frmMain").children()
Object length=42
>>> $("#frmMain").children().filter(":checkbox")
Object length=3
Any hints on how to do the loop correctly?
don't think you need quotations on this:
var child = $("this");
try:
var child = $(this);
jQuery has an excellent function for looping through a set of elements: .each()
$('#formId').children().each(
function(){
//access to form element via $(this)
}
);
Depending on what you need each child for (if you're looking to post it somewhere via AJAX) you can just do...
$("#formID").serialize()
It creates a string for you with all of the values automatically.
As for looping through objects, you can also do this.
$.each($("input, select, textarea"), function(i,v) {
var theTag = v.tagName;
var theElement = $(v);
var theValue = theElement.val();
});
I have used the following before:
var my_form = $('#form-id');
var data = {};
$('input:not([type=checkbox]), input[type=checkbox]:selected, select, textarea', my_form).each(
function() {
var name = $(this).attr('name');
var val = $(this).val();
if (!data.hasOwnProperty(name)) {
data[name] = new Array;
}
data[name].push(val);
}
);
This is just written from memory, so might contain mistakes, but this should make an object called data that contains the values for all your inputs.
Note that you have to deal with checkboxes in a special way, to avoid getting the values of unchecked checkboxes. The same is probably true of radio inputs.
Also note using arrays for storing the values, as for one input name, you might have values from several inputs (checkboxes in particular).
if you want to use the each function, it should look like this:
$('#formId').children().each(
function(){
//access to form element via $(this)
}
);
Just switch out the closing curly bracket for a close paren. Thanks for pointing it out, jobscry, you saved me some time.
for me all these didn't work. What worked for me was something really simple:
$("#formID input[type=text]").each(function() {
alert($(this).val());
});
This is the simplest way to loop through a form accessing only the form elements. Inside the each function you can check and build whatever you want. When building objects note that you will want to declare it outside of the each function.
EDIT
JSFIDDLE
The below will work
$('form[name=formName]').find('input, textarea, select').each(function() {
alert($(this).attr('name'));
});

Categories