Gene Sy
Gene Sy

Reputation: 1655

Store elements inside an array then use it later in jquery

var els = [];
els.push($("#something"));

I need to add this to the array because the properties of #something will be changed and I need to get it's original properties (height,width position etc.)

how do I now use the element inside els array?

Upvotes: 3

Views: 22111

Answers (5)

Xotic750
Xotic750

Reputation: 23472

If you really want to store a copy of the "element" and its "css" so that you have everything available, then you will need to do something like this. (examples in POJS and jquery)

CSS

#target {
    position: relative;
    top: 100px;
    left: 150px;
    height: 50px;
    width: 70px;
}

HTML

<div id="target">Text</div>

Javascript

// IE5+ support
function snapshot(node) {
    var computedStyle = {},
    style = {},
    prop;

    if (typeof document.defaultView.getComputedStyle === "function") {
        computedStyle = document.defaultView.getComputedStyle(node, null);
    } else if (node.currentStyle) {
        computedStyle = node.currentStyle;
    } else {
        throw new Error("Unable to get a computed style.");
    }

    for (prop in computedStyle) {
        if (computedStyle.hasOwnProperty(prop)) {
            style[prop] = computedStyle[prop];
        }
    }

    return {
        node: node.cloneNode(true),
        style: style
    }
}

// Whatever jquery supports
$.fn.snapshot = function () {
    var node = this.get(0),
        computedStyle = {},
        style = {},
        prop;

    if (typeof document.defaultView.getComputedStyle === "function") {
        computedStyle = document.defaultView.getComputedStyle(node, null);
    } else if (node.currentStyle) {
        computedStyle = node.currentStyle;
    } else {
        throw new Error("Unable to get a computed style.");
    }

    for (prop in computedStyle) {
        if (computedStyle.hasOwnProperty(prop)) {
            style[prop] = this.css(prop);
        }
    }

    return {
        node: this.clone(true),
        style: style
    }
}

var snap1 = snapshot(document.getElementById("target")),
    snap2 = $("#target").snapshot();

console.log(snap1, snap2);

On jsfiddle

If, on the other hand, what you really are after is the bounding client rectangle information. Then you could do something like this.

CSS

#target {
    position: relative;
    top: 100px;
    left: 150px;
    height: 50px;
    width: 70px;
}

HTML

<div id="target">Text</div>

Javascript

// IE5+ support
var getBoundingClientRect = (function () {
    // Gecko < 1.9.1 test
    var test = document.body.getBoundingClientRect();

    // Gecko < 1.9.1
    if (!test.hasOwnProperty("height") || !test.hasOwnProperty("width")) {
        return function (node) {
            var rect = target.getBoundingClientRect();

            rect.height = rect.bottom - rect.top;
            rect.width = rect.right - rect.left;

            return rect;
        };
    }

    // Gecko >= 1.9.1
    return function (node) {
        return target.getBoundingClientRect();
    };
}());

// Whatever jquery supports
$.fn.getBoundingClientRect = function () {
    var offset = this.offset(),
        height = this.height(),
        width =this.width(),
        rect = {
            width: width,
            height: height,
            top: offset.top,
            left: offset.left,
            bottom: offset.top + height,
            right: offset.left + width
        };

    return rect;
}

var rect1 = getBoundingClientRect(document.getElementById("target")),
    rect2 = $("#target").getBoundingClientRect();

console.log(rect1, rect2);

On jsfiddle

how do I now use the element inside els array?

Use standard Array methods to access the individual elements you stored within els.

There are also some jquery methods available, depending on what you want to do, for example looping jQuery.each

What you "want to do" with the information is up to you, you haven't specified that in your question.

Upvotes: 1

Ginden
Ginden

Reputation: 5317

You are trying to create static copy of jQuery object. It's obviously impossible (or very hard to do). You should save only important properties of an object, in way: {value: something.val()}

Of course, you can create function for this.

function xyz (Element, List) {
    // in List you can use form 'val' for methods without arguments and ['attr', 'argument']
    // for others.
    // eg. ['val', ['attr', 'id'], ['css', 'height']]
    Element = $(Element); // to be sure it's jQuery Object
    var InfoList = {},
    i, it, MethodName, MethodArg;
    for (i = 0; i < List.length; i++) {
        it = List[i];
        if (typeof it === 'object') {
            MethodName = it[0];
            MethodArg = it[1];
            if(!InfoList[MethodName])
                InfoList[MethodName] = {};
            InfoList[MethodName][MethodArg] = Element[MethodName](MethodArg);
        }
        else if (typeof it === 'string') {
            InfoList[it] = Element[it];
        }
        else {
            console.log('O.o');
        }
    }
    return InfoList;
}

Example of output (I used th): JSON.stringify(xyz($('#hlogo'), ['html', ['attr', 'id'], 'height', ['css', 'color']]))

{
  "html": "\n                <a href=\"\/\">\n                    Stack Overflow\n                <\/a>\n            ",
  "attr": {
    "id": "hlogo"
  },
  "height": 61,
  "css": {
    "color": "rgb(0, 0, 0)"
  }
}

Upvotes: 0

Christian Duvall
Christian Duvall

Reputation: 409

I would not store the entire object if there are only a few properties required.

$something = $('#something');
els[$something.attr('id')] = { 
  width: $something.width(),
  height: $something.height(),
  offset: $something.offset() };

console.log(els['something']);

Upvotes: 3

relic
relic

Reputation: 1692

You can add as many objects to the array as you like, then perform actions or get values from each of them using the array index.

var els = [];
els.push($("#something"))
   .push($("#something-else"))
   .push($("#another"))
   .push($("#mydiv"))
;

... like so:

els[0].width();
els[1].css('height');
els[2].css('width','300px');
els[3].position();

els.each(function(){
    // Do stuff
}

You're essentially doing the same thing as if you saved the jquery object as a variable, and you can perform any of the same actions you might perform on that variable (or on the jquery selection directly) on the array's reference to it.

Upvotes: 2

Pointy
Pointy

Reputation: 413702

Well to use the saved jQuery object you'd just use normal array indexing:

els[0].css("backgroundColor", "purple");

Now, you say that you want to save that jQuery object to preserve its state. That won't work; the jQuery object is just a wrapper that provides access to the DOM element(s) chosen by your selector. It does not copy or preserve the state of the DOM, however. If the DOM changes, then those changes will be reflected by that jQuery object and old property values won't be available.

If you want to preserve the state of the element, you have to do it explicitly. For example, if "something" is an <input>, you could save its value:

var savedValue = $('#something').val();

If you want to save the properties to an array:

var els = [];
els.push({
  height: $('#something').height(),
  width: $('#something').width(),
  position: $('#something').position()
});

That'll push a whole new object (not a jQuery object; just a plain object with properties) to capture your DOM state.

Now you've got a copy of the "value" property, and subsequent DOM updates won't change that.

Upvotes: 2

Related Questions