-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbasic-framed-content.html
181 lines (151 loc) · 5.39 KB
/
basic-framed-content.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<!--
When this is placed on a page framed by a basic-seamless-iframe element, the
two elements will cooperate to handle common cross-frame scenarios:
1: The outer basic-seamless-iframe can set and inspect the content of the
inner basic-framed-content element.
2: The outer basic-seamless-iframe can adjust its height to exactly contain the
inner basic-framed-content element.
The two elements communicate with postMessage, which is not supportedy by IE10.
The outer element will auto-size to be only as tall as the basic-framed-content
element, so the height of elements on the framed page outside the basic-framed-
content won't be taken into account. In order for the outer basic-seamless-
iframe to set its height correctly, the framed page hosting the basic-framed-
content instance should not have any margin, padding, or other elements outside
the basic-framed-content.
@element basic-framed-content
@demo ../packages/sample/basic-seamless-iframe/index.html
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../basic-shared/basic-shared.html">
<dom-module id="basic-framed-content">
<template>
<style>
:host {
display: block;
}
</style>
<content></content>
</template>
</dom-module>
<script>
Polymer({
// attached: function() {
// // This is similar to what basic-element does to observe content changes,
// // but here we also want to observe attribute changes.
// var observer = new MutationObserver(function() {
// this._contentChanged();
// }.bind(this));
// observer.observe(this, {
// attributes: true,
// characterData: true,
// childList: true,
// subtree: true
// });
// if (this.childNodes.length > 0) {
// this._contentChanged();
// }
// },
behaviors: [Basic.ContentChanged],
/**
* Broadcast the element's current content to the contained page.
*
* @method broadcastContent
*/
broadcastContent: function() {
var content = Polymer.dom(this).innerHTML;
this._postMessageToParent('framedContentResponse', content);
},
/**
* Broadcast the element's current height to the contained page.
*
* @method broadcastHeight
*/
broadcastHeight: function() {
this._lastHeight = this._getHeight();
this._postMessageToParent('framedHeightResponse', this._lastHeight);
},
// Our content is changed. Broadcast the new content and the height (if the
// height changed too).
// TODO: Add support Basic.ContentChanged to observe attribute changes in
// children (but not attribute changes on the top-level element).
contentChanged: function() {
this.broadcastContent();
// The loading of data will *not* count as a DOM mutation event, so we have
// to explicitly listen for load events on elements that have them.
this._listenForLoadEvents('img');
this._listenForLoadEvents('iframe');
// If the height changed, broadcast that too. Our own height won't be
// available immediately; wait a tick to give the browser a chance to re-
// render first.
window.setTimeout(function() {
this._checkForHeightChange();
}.bind(this), 1);
},
is: 'basic-framed-content',
ready: function() {
window.addEventListener('WebComponentsReady', function() {
this._postMessageToParent('framedPolymerReady'); // For backward compat
this._postMessageToParent('framedWebComponentsReady');
}.bind(this));
window.addEventListener('message', function(event) {
if (!event.data) {
return;
}
switch (event.data.message) {
case 'setContent':
this.innerHTML = event.data.detail;
// Promote any links to document head.
var links = Polymer.dom(this).querySelectorAll('link');
Array.prototype.forEach.call(links, function(link) {
document.head.appendChild(link);
});
break;
case 'requestContent':
this.broadcastContent();
break;
case 'requestHeight':
this.broadcastHeight();
break;
}
}.bind(this));
},
_checkForHeightChange: function() {
if (this._lastHeight !== this._getHeight()) {
// Height changed since the last time we checked.
this.broadcastHeight();
}
},
_getHeight: function() {
return Math.ceil(this.offsetHeight);
},
// The last known height of this element
_lastHeight: null,
// Listen for load events on children of the specified tag type.
// TODO: Share this with basic-framed-content.
_listenForLoadEvents: function(tag) {
var childNodes = Basic.ContentHelpers.flattenChildNodes(this);
Array.prototype.forEach.call(childNodes, function(child) {
if (child.localName === tag) {
child.addEventListener('load', function() {
this.recalc();
}.bind(this));
}
}.bind(this));
},
_postMessageToParent: function(message, detail) {
var payload = {
message: message,
source: location.href
};
if (detail != null) {
payload.detail = detail;
}
// TODO: For better security, set a target origin on the message. If we're
// responding to a request, we could keep track of the origin of the request
// and use that as the target origin for the response. This would get a bit
// tricky for cases where we want to post a message that's not directly in
// response to a request.
window.parent.postMessage(payload, '*');
}
});
</script>