3

I'm working on essentially a WYSIWYG designer that allows the end-user to pick colors via [input type="color"] fields. This interface has the inputs on the left side and on the right side is an iFrame pointing to the generated preview. Typically, when an input is clicked and the color is changed, it calls function update (bound by a backbone view via change event on the input field). This update function then changes the CSS values in the iFrame for purposes of live preview. This is working fine.

However, I am building a unit test page that is essentially testing that changing an input field to a certain color will indeed change the color in the preview. Essentially this: "Change input to PINK. Did that input's corresponding CSS selector on the preview change to PINK?"

The structure of the unit test page is that the designer is loaded in via an iFrame. So now we have:

  • Layer 0: unit test report
  • Layer 1: color changing inputs
  • Layer 2: real time preview

So here's the problem: When the unit tests are running, it successfully changes the value of the input fields but the subsequent change event doesn't seem to be caught by the view so the real time preview does not update.

Here is the code:

for (i in testable) {
    item = testable[i];
    item.element.val(tempColor);
    item.element.trigger('change');
}

If I pull this out of the scope of the testing module and use the browser's console, this code has the same effect (input updates, but trigger never called):

$("#testFrame").contents().find('input#cat_RowColoralternate').val('#AAEFCC').trigger('change')

To prove that the event exists and does actually work, if I load it directly without the testing layer (e.g., loading application directly), this code works exactly how it's expected.

$(document).find('input#cat_RowColoralternate').val('#AAEFCC').trigger('change');

The only difference is the additional iFrame layer, so my theory is that the event isn't being propagated from layer 0 to layer 1.

1
  • 1
    One thing I've found in the past is different jQuery references in the different pages. What if you get hold of the jQuery object within the inner frame, and attempt to use that to fire the trigger, rather than trying to fire it with the jQuery object in the outer frame? Commented Nov 12, 2014 at 15:21

1 Answer 1

3

I don't believe you can trigger jQuery events across frame in this way. The call to .trigger() is happening in the parent frame, and so doesn't work correctly/at all in the jQuery object in the iframe.

Instead, you need to get hold of the jQuery object inside the iframe, and perform the trigger there:

var framejQuery = $('#testFrame').get(0).contentWindow.$;
framejQuery('input#cat_RowColoralternate').val('#AAEFCC').trigger('change');
Sign up to request clarification or add additional context in comments.

2 Comments

This worked, thanks! Is this intentional behavior or is it a bug? If I can target and interact with an element in another context, I would think I should be able to trigger an event against it.
I'm not sure - I've never delved into it enough to find out. It's certainly arguably a bug in that jQuery ought to propagate these events itself, but whether they see it that way or not is another matter

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.