0

Say I have an array of strings. And I want to prepend each of these strings with a fixed (common) string. I know that in Javascript, strings can be concatenated like strM = str1 + str2 + str3 + ... + strN or strM = concat(str1, str2, str3, ..., strN). Consider this piece of code.

var defImgDirPath = 'res/img/';
$([
  'home-icon-dark.png',
  'home-icon-light.png'
]).each(function() {
  /*
   * Prepend each string with defImgDirPath
   */
});

Now I can't do this = defImgDirPath + this; (I was stupid enough to try)

Also, I tried return (defImgDirPath + this); but that wouldn't work either.

I am thinking something along the lines of a function like this.prependString(defImgDirPath); but does such a function exist? If not, how do I write one?

Note: I know it can be done much easily and simply with a for loop too, but what's the fun in that? :)

Zia Ur Rehman
  • 1,141
  • 2
  • 11
  • 20
  • I might be fuzzy with what you are asking, but what are you putting the path into when you need to use it? Are you trying to use it in an img tag? Could you just concatenate when you need to use it if the path prefix is a constant? – Bmo Mar 28 '13 at 10:46
  • You have to pass parameters to `.each` http://jsfiddle.net/hj2XJ/ – sofl Mar 28 '13 at 10:47
  • 1
    It doesn't always make sense to use jQuery... When you can use regular js, you should. – Jeff Shaver Mar 28 '13 at 10:52
  • Vanilla js is just fine. When I moved from Prototype to jQuery I had to do some rewriting except for the parts that were written with vanilla js. What's wrong with for loop? – hade Mar 28 '13 at 11:05
  • @Bmo: I'm trying to preload the images. There's an icon `home-icon-dark.png`. When hovered, the icon changes (transitions) to `home-icon-light.png`. When the icon is hovered first time, the browser starts fetching `home-icon-light.png` and the effect is ruined. Though it works fine once it's fetched. I'll preload `home-icon-light.png` by creating an array of Javascript `Image()`s while the rest of the DOM elements are being fetched, so when the icon is hovered for the first time, the `home-icon-light.png` is already fetched and the transition will be seamless. :) – Zia Ur Rehman Mar 28 '13 at 11:07
  • @JeffShaver Yeah, when I'm developing professionally. Right now I'm doing it for the fun of it. I wanted to know if it could be done in a specific way. I don't suppose there's something wrong with that. :) Cheers! – Zia Ur Rehman Mar 28 '13 at 11:10

5 Answers5

1
var defImgDirPath = 'res/img/';
var images = [
    'home-icon-dark.png',
    'home-icon-light.png'
];
$(images).each(function(idx, val) {
  images[idx] = defImgDirPath + val;
});

console.log(images);
Cristi Pufu
  • 9,002
  • 3
  • 37
  • 43
1

In latest standards of javascript (ECMA 5), You can do this without jquery:

var defImgDirPath = 'res/img/';

['home-icon-dark.png','home-icon-light.png'].map(function(i) { 

        return defImgDirPath + i;  });

EDIT : Besides, map function of jquery works similar too.

loxxy
  • 12,990
  • 2
  • 25
  • 56
0

The problem is that you are changing a copy of the item in the array, so the array will be unaffected.

Loop through the indexes in the array and put the result back in the array:

var arr = [ 'home-icon-dark.png', 'home-icon-light.png' ];

for (var i = 0; i < arr.length; i++) {
  arr[i] = defImgDirPath + arr[i];
}

If you really want to use a loop method from jQuery, then you would need to use map, so that you get the result as an array. Note that you need to use the parameters of the callback function, as this is not the item from the array:

arr = $.map(arr, function(str){
  return defImgDirPath + str;
});
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • I said in the question that I know it can be done much easily using a `for` loop. I wanted to do it using `$.each`. However, I didn't know about `$.map`. Still, `$.each` looks more _elegant_ (to me at least). Thanks for the answer. Cheers! – Zia Ur Rehman Mar 28 '13 at 10:51
  • @ZiaUrRehman: You can use `$.each` instead of a regular loop as you get the index of the iteration, but it's not very elegant as the callback function will get a reference to the array in a closure and change it directly instead of returning the result. – Guffa Mar 28 '13 at 11:09
  • You mean the `$.each` won't return an array of strings prepended with `defImgDirPath`? – Zia Ur Rehman Mar 28 '13 at 11:16
  • @ZiaUrRehman: Yes, as it won't return anything. You would just be using `$.each` as a different and less efficient way of writing a `for`. – Guffa Mar 28 '13 at 11:32
0

In Javascript, this always refers to an object (the current context object), so it won't ever be a string, and therefore trying to concatenate it with another string will fail, as you've found.

However, there's no need to use jQuery or objects for what you're doing; you're just prepending a known value to the start of each of an array of strings.

Let's rewrite it using standard Javascript, without the jQuery complications...

var defImgDirPath = 'res/img/';
var images = [
  'home-icon-dark.png',
  'home-icon-light.png'
];

for(var count=0; count<images.length; count++) {
    images[count] = defImgDirPath + images[count];
}

I've put the images array into a variable to make it easier to see what the actual loop code is doing. As you can see, it's a pretty simple loop; no need for jQuery magic here.

hope that helps.

Spudley
  • 166,037
  • 39
  • 233
  • 307
0

this.prependString(defImgDirPath);

No. Strings are immutable in JavaScript. Concatenation to a new string would be fine, and using .concat it would look like

var newString = defImgDirPath.concat(this); // no static function!

If not existing, how do I write one?

You can't, as assigning object to "this" is impossible.

Instead, you have to assign to a property of the array you're working on (using the static $.each instead of working on a collection):

var arr = [
  'home-icon-dark.png',
  'home-icon-light.png'
];
$.each(arr, function(i) {
   arr[i] = defImgDirPath + this;
});
arr[0] // res/img/home-icon-dark.png

Also I tried return (defImgDirPath + this);

You would need to use map for that, creating a new array:

var arr = $.map([
  'home-icon-dark.png',
  'home-icon-light.png'
], function(str) {
    return defImgDirPath + str;
});

Of course, it might be easier without jQuery at all:

for (var i=0; i<arr.length; i++) {
    arr[i] = defImgDirPath + arr[i];
}

And also map is available as a native function (not in outdated browsers):

var arr = [
  'home-icon-dark.png',
  'home-icon-light.png'
].map(function(str) {
    return defImgDirPath + str;
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • When using the `map` method you have to use the parameters of the callback function, as `this` refers to the `window` object. – Guffa Mar 28 '13 at 10:53
  • @Guffa: Thanks, fixed. Would need to have been `$([…]).map(function() { return defImgDirPath + this; }).get()` for using `this` :-/ – Bergi Mar 28 '13 at 10:59