I have a function for a jQuery plugin that loop through some images.
//load images
function ImageSettings(config, fileNames) {
//loop through the array in the second argument
for (var x = 0; x < fileNames.length; x++) {
//create image
$("<img />").attr({
id: fileNames[x],
src: config.imgDir + fileNames[x] + config.imgFormat,
title: fileNames[x] + " layout"
}).appendTo("#" + config.imgContainer);
}
};
Further down my plugin, I need to pass the image attr ID inside a unordered list item , but my variable is located inside my function called fileNames.
so if use:
$(config.sidebar).append('<ul>' + fileNames + '</ul>');
//I get a string like: home, about, contact but I need it to be styled in a list item
If I use the split method to remove the " , " then I get an unknown method split.
So, is it possible to pass the function and variable inside? like for instance so I work around the unknown method?
$(config.sidebar).append('<ul>' +
ImageSettings(fileNames[x]).each(function() {
$( this ).wrap( "<li>" );
+ '</ul>');
I thought about using something like $('img').attr('id') and then style this in a list item but because I will have several images on my page but not all will be loaded and not all will need to be wrapped in a list item. Hence the reason why I would like to use my variable inside the function. Thank you.
You code seems a bit convoluted. Does this solve your problem?
Here's the code:
var config = {
"imgContainer": "imgContainer",
"sidebar": "ul",
"imgDir": "",
"imgFormat": "jpg"
};
var fNames= [/* list of file names */];
function ImageSettings(fileNames) {
//loop through the array in the second argument
for (var x = 0; x < fileNames.length; x++) {
var fname = fileNames[x];
//create image
$("<img />").attr({
id: fname.substr(fname.lastIndexOf("/"+1, fname.length)),
src: config.imgDir + fname + "."+config.imgFormat,
title: fname.substr(fname.lastIndexOf("/"+1, fname.length)) + " layout"
}).appendTo("#" + config.imgContainer);
$(config.sidebar).append('<li>' + fname + '</li>');
}
}
ImageSettings(fNames);
Related
I have this array of objects being loaded:
$(document).ready(function () {
$("<div></div>").load("/Stats/Contents #stats", function () {
statcount = $(".list-group-item", this).length;
for (var j = 0; j < statcount; j++) {
statList.push(stat);
}
for (var i = 0; i < statcount; i++) {
statList[i].statId = document.getElementById("statId-" + (i + 1) + "").value;
statList[i].productDescription = document.getElementById("productType-" + (i + 1) + "").value;
statList[i].lastMeasuredInventoryAmount = document.getElementById("statLastMeasureAmount-" + (i + 1) + "").value;
}
)}
)}
.... and so on
Then I get the changed values and save them, however, in the ajax post call, all of the array objects are same (the last one assigned), looks like they get overwritten.
Any ideas? I saw these deferred/promise type code but not sure if there's simpler way.
Thanks.
It sounds like you take the statList array and then push that up to the server, with any respective change. Rather than building and maintaining a list like this, have you thought of switching it around and just grabbing the results out of the markup and building up the array at save point?
$("btnSave").on("click", function(e) {
var data = [];
$(".list-group-item").each(function() {
data.push({
statId: $(this).find(".statid").val(),
.
.
})
});
You wouldn't need to give every element an ID (but could) as my sample uses CSS classes to find the element within the current list item. Additionally, if these are inputs, you could serialize them from the root element more efficiently...
I made this helper function to assist me with stuff
function formToObject(form) {
var items = form.querySelectorAll("[name]");
var json = "{";
for (var i = 0; i < items.length; i++) {
json += '"' + items[i].name + '":"' + items[i].value + '",';
}
json = json.substring(0, json.length-1) + "}";
return JSON.parse(json);
}
There is a problem with it though, it doesn't exclude forms that are inside the form element thats passed to it. Didn't come up before but now it seems to be necessary. Is there a way to write the selector string in a way that it would exclude any children of other forms inside it?
Like "[name]:not(form *)" (which obviously doesn't work)
EDIT: got a little closer with "[name] :not(fieldset) *" but that also ignores the immediate fieldset children
I have this recursive code that transverses the DOM and adds a prefix to the id for all input tags.
I would like to change this to a more elegant jQuery, but I'm not sure how to structure the selectors or if the selectors need to be recursive..
cheers,
function set_inputs(obj, prefix){
for (var s=0;s< obj.childNodes.length; s++){
var node = obj.childNodes[s];
if(node.tagName == "INPUT"){
node.id= prefix +'_' + node.id;
node.name= prefix +'_' + node.name;
}
else{
set_inputs(node,prefix);
}
}
}
For the entire DOM.
It would be as simple as:
var prefix;
$("input").each(function(i,elem)
{
$(elem).attr("id", prefix + "_" + $(elem).attr("id"));
});
You could change the selector : $("input") - which selects all the doms inputs, to any other selector to target different elements.
If you wanted it separately in a function then:
function() set_inputs(col, prefix) {
col.each(function(i,elem)
{
$(elem).attr("id", prefix + "_" + $(elem).attr("id"));
});
}
You would then use it like this:
set_inputs($("input"), "abc");//prefix ALL the DOM's inputs with abc
set_inputs($("input.btn"), "abc");//prefix inputs with the css-class btn
No particular need to use jQuery for this either. It could be done in plain javascript without recursion using getElementsByTagName() like this:
function set_inputs(obj, prefix) {
var nodes = obj.getElementsByTagName("input");
for (var i = 0, len = nodes.length; i < len; i++) {
if (nodes[i].id) {
nodes[i].id = prefix + '_' + nodes[i].id;
}
if (nodes[i].name) {
nodes[i].name = prefix + '_' + nodes[i].name;
}
}
}
P.S. I added protection in the code that your code did not have in case input tags exist without an id or a name attribute so the code won't error out if it encounters that. If you didn't want that protection, the code would be shorter like this:
function set_inputs(obj, prefix) {
var nodes = obj.getElementsByTagName("input");
for (var i = 0, len = nodes.length; i < len; i++) {
nodes[i].id = prefix + '_' + nodes[i].id;
nodes[i].name = prefix + '_' + nodes[i].name;
}
}
You call this function by passing it two arguments, the DOM object that represents the top of the part of the DOM tree you want to search for input tags in and the prefix you want to add to the IDs. If you do something like this: set_inputs(document.body, "test") it will search the entire document. If you do something like this: set_inputs(document.getElementById("top"), "test"), it will only search a portion of the DOM tree (the part under the id=top element). You can pass it any arbitrary DOM object and it will only search the nodes in that hierarchy.
Just want to suggest a small change
$('input').each(function(){
this.id = prefix + this.id;
});
To pull the deep nested inputs, use jquery find(). This solution is much simpler code than recursive javascript. I did leave out the steps verifying the existence of id and name attributes which should be done for production code.
$(obj).find("input").each(function(){
$(this).attr('id',prefix + "_" + $(this).attr('id'));
$(this).attr('name',prefix + "_" + $(this).attr('name'));
});
I have a loop which won't run using Prototype + Scriptaculous. It runs once for the first object in my array then stops.
var myMessages = new Object();
myMessages = ['success','info','warning','error']; // define the messages types
function hideAllMessages()
{
var messagesHeights = new Array(); // this array will store height for each
enter code here
// This one runs just once for the first item in the array
var i = 0;
myMessages.each(function(element) {
alert(element);
messagesHeights[i] = $('.' + element).getHeight();
i++;
$$('.' + element + ' message').invoke('hide');
});
//This won't run at all===============================
for (var index = 0; index < myMessages.length; index++)
{
messagesHeights[index] = $('.' + myMessages[index]).getHeight();
$('x').hide();
//$('.' + myMessages[i]).css('top', -messagesHeights[i]); //move element outside viewport
}
}
I'm not a prototype user, but here's what I see so far:
$ is for IDs. I believe you need $$ here:
$$('.' + element)
This returns an Array, so I think you need invoke() like this:
$$('.' + element).invoke('getHeight');
Also, .each() passes the index as the second argument to the callback, so you don't need to maintain your own i.
myMessages.each(function(element, i) {
Also, this:
$$('.' + element + ' message')
...would seem to be looking for elements with the tag named message. I assume you want a class instead.
$$('.' + element + ' .message').invoke('hide');
I have an image updater. I am loading by JSON the exact same file/partial that show my images.
I would like to write a loop that runs through an index and replaces every image with its equal.
This is the first div in my json object :
[{
"photo": {
"position":1,
"photo_file_size":45465,
"created_at":"2010-10-05T09:51:13-04:00",
"updated_at":"2010-10-05T09:52:29-04:00",
"photo_file_name":"tumblr_l0x861Yc5M1qbxc42o1_400.jpg",
"is_cropped":true,
"crop_h":null,
"photo_content_type":"image/jpeg",
"id":216,
"caption":null,
"crop_w":null,
"photo_uploaded_at":null,
"crop_x":null,
"processing":false,
"gallery_id":26,
"crop_y":null
}
},
...
The next div in that json object would be something like gallery_photos_attributes_1_id .
Update
This is what I got so far.. but the load() method doesn't work correctly. I get a "ONLY GET REQUESTS ALLOWED"
$.getJSON(url, function(data) {
for (var i = 0; i < data.length; i ++) {
url2 = "/organizations/" + 1 + "/media/galleries/" + 26 + "/edit_photo_captions"
var image = $("#gallery_photos_attributes_" + i + "_caption");
url_str = image.siblings("img").attr("src").substr(0, str.lastIndexOf("/"));
image.siblings("img").load(url2, image.siblings("img"));
};
})
Although I'm not 100% I got you right, try this piece of code.
var url = "/organizations/" + organization + "/media/galleries/" + gallery + "/update_photo_index"
$.getJSON(url, function(data) {
// the outer is an array, so just loop as usual
for (var i = 0; i < data.length; i++) {
// fetch something for the current photo
var caption = $("#gallery_photos_attributes_"+ data[i].photo.id +"_caption");
// update source
caption.siblings("img").attr("src","/path/to/images/"+data[i].photo.photo_file_name+"?c="+parseInt(Math.random()*10000));
// update caption
caption.html(data[i].photo.caption);
// and so on...
}
});
Remember that in JSON "[ ... ]" describes an array whereas "{ ... }" describes an object. With an array you can just loop as with every other javascript array. If you got an object, it's like any other javascript object whose fields are accessible either with object.field or object['field']. So using JSON in javascript is nearly a no-brainer.
Hope that helps.