окно.postMessage между iframe и его родителем с Angular: у кого-нибудь есть рабочий пример?
у кого-нибудь есть рабочий пример как отправлять и получать окно.postMessage () вызывает в angular? Я нашел ng-post-message модуль на github и ngmodules, но я смотрю на этот код, и он не имеет для меня большого смысла, и в документации отсутствует рабочий пример.
Edit: добавить мою неудачную попытку
вид
<div simulation-host element="thing in things"></div>
</div>
<div id="debugConsole">
<h1>MESSAGE CONSOLE</h1>
<p id="debugText"></p>
</div>
модель
$scope.things =
[
{
"location" : "Foobar",
"resource" : $sce.trustAsResourceUrl("http://external.domain:14168/Foo/Bar"),
"title" : "Launch"
}
];
моя попытка директива
var simulationFrameHost = angular.module('proxy.directives', []);
simulationFrameHost.config(function ($sceDelegateProvider){
//URL Regex provided by Microsoft Patterns & Practices.
$sceDelegateProvider.resourceUrlWhitelist(['^(ht|f)tp(s?)://[0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*(:(0-9)*)*(/?)([a-zA-Z0-9-.?,'/\+&%$#_]*)?$','self']);
});
simulationFrameHost.directive('simulationHost', ['$window',function($window) {
return {
retrict: 'ACE',
transclude: 'element',
replace: true,
scope: true,
template: [
'<ul>',
'<li>',
'<span>',
'<a href="#">',
'{{thing.location}}',
'</a>',
'</span>',
'<messenger>',
'<iframe ng-src="{{thing.resource}}" />',
'</messenger>',
'</li>',
'</ul>'
].join(''),
compile: function (tElement, tAttrs, transclude) {
var interval;
var show = function(msg)
{
var debugText = document.getElementById("debugText");
if(debugText){
debugText.innerHTML += msg + "<br/>";
}
};
var rpt = document.createAttribute('ng-repeat');
rpt.value = tAttrs.element;
console.log(tAttrs.element);
tElement[0].children[0].attributes.setNamedItem(rpt);
$(tElement[0].children[0].children[0].children[0]).on("click", function(event){
console.log(event);
var iframe = tElement[0].children[0].children[1].children[0].contentWindow;
show("Initiating connection with: " + event.currentTarget.host);
var message = {
action: 'syn',
param: 'connection'
};
interval = setInterval(function(){
//*****************************************
iframe.postMessage(JSON.stringify(message), 'http://'+ event.currentTarget.host);
//*****************************************
}, 500);
return false;
});
}
}
}]);
рабочий устаревший код, который я пытаюсь адаптировать к Angular
обратите внимание, что этот код использует всплывающее окно, а не iframe; столкнулся с осложнением, что IE postMessage между окнами сломан, поэтому должен вернуться к iframe.
разметки
<body>
<div id="debugConsole">
<h1>MESSAGE CONSOLE</h1>
<p id="debugText"></p>
</div>
<h1>This is a test</h1>
<ul>
<li>
<a href= "http://external.domain:14168/Foo/Bar" target="_blank" ><p>Foobar</p></a>
</li>
</ul>
<script src="js/jquery-1.10.2.min.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="js/SCORM_API_wrapper.js"></script>
<script src="js/json2.js"></script>
<script src="js/plugins.js"></script>
<script src="js/index.js"></script>
</body>
.js
$('a').on("click",function(event){
console.log(event);
var pop = window.open(event.currentTarget.href, 'poop');
show("Initiating connection with: " + event.currentTarget.host);
var message = {
action: 'syn',
param: 'connection',
};
interval = setInterval(function(){
pop.postMessage(JSON.stringify(message), 'http://'+ event.currentTarget.host);
}, 500);
return false;
});
$(window).on("message", function(e) {
clearInterval(interval);
var eventData = JSON.parse(e.originalEvent.data);
show("Message received from: " + e.originalEvent.origin);
if(eventData.action) {
switch (eventData.action) {
case 'syn-ack':
ack(e.originalEvent, eventData.param, eventData.value);
break;
case "set":
show("Set request received: " + e.originalEvent.data);
set(eventData.param, eventData.value);
break;
case "get":
show("Get request received: " + e.originalEvent.data);
var value = get(eventData.param);
var response = {
action: "response",
type: "get",
param: eventData.param,
value: value
};
e.originalEvent.source.postMessage(JSON.stringify(response), channel);
break;
}
}
});
в компиляции моей директивы, я пытаюсь привязать событие click к созданному тега "Anchor". Я попытка получить щелчок для публикации сообщения в iframe, но iframe.метод postMessage ничего не делает. Он просто уходит в пустоту, и я работаю над этим с 10 утра. Мои глаза начинают стекленеть : п
Edit: добавление требования расширения (теперь, когда у меня есть действующий код) для общей директивы обмена сообщениями между отдельными контейнерами, независимо от типа контейнера:
1)iframe to parent
2)window to window
(
у меня был устаревший код, работающий с окном для обмена сообщениями, имея окно, которое породило второе сообщение "syn" сообщение к нему сразу после его создания. Затем второе окно получило сообщение как " syn "и сохранило отправителя как messageHandle, чтобы он мог поддерживать канал для публикации возвращаемых сообщений, а затем вернул" syn-ack."Инициатор последовал за "ack" , а вторичное окно получило ack и продолжило своя работа. (Если ack не вернулся до тайм-аута, я зарегистрировал, что соединение не удалось, а затем вторичное окно опросило интервал, чтобы попытаться восстановить соединение)
2 ответов
Я не мог заставить это работать с угловой директивой. Я потратил впустую всю ночь, пытаясь сделать это "правильно", и жалею, что не выбросил эту идею раньше, потому что мои требования действительно не оправдывали этого. Эта вещь не должна масштабироваться, потому что это целевое программное обеспечение для создания прокси-сервера обмена сообщениями между системами X-домена.
'use strict'
var app = angular.module('domain.system.controllers', ['services.proxy.mine']);
app.controller('ProxyCtrl', ['$scope', '$routeParams', '$window', '$sce', 'MyService',
function ( $scope, $routeParams, $window, $sce, MyService)
{
$($window).on("message", function(e){
var message = JSON.parse(e.originalEvent.data);
if(message.recipient){
switch(message.recipient){
case: "ProxyCtrl":
//handle message;
break;
}
}
}
}
]);
меня на 100% интересует подробное объяснение того, как преобразовать этот код в действующую директиву.
только что наткнулся на этот пост, это может вам помочь.
(function() {
'use strict';
angular
.module('postmessage')
.factory('iFrameMessagingService', iFrameMessagingService);
iFrameMessagingService.$inject = ['$window', '$location', '$rootScope', '$log'];
function iFrameMessagingService($window, $location, $rootScope, $log) {
var service = {
sendMessage : sendMessage
};
activate();
return service;
function activate(){
activateIncomingMessageHandler();
}
function activateIncomingMessageHandler(){
$window.addEventListener('message', function(event){
if (typeof(event.data) !== 'undefined'){
// handle message
}
});
}
function sendMessage(message){
// Dispatch the event.
$log.debug(message);
if($window.parent !== $window){
$window.parent.postMessage(message, '*');
}
}
}
})();