Skip to content

Instantly share code, notes, and snippets.

@corlaez
Created November 20, 2020 19:44
Show Gist options
  • Save corlaez/a06d29606bd3ce527070932a40cc0110 to your computer and use it in GitHub Desktop.
Save corlaez/a06d29606bd3ce527070932a40cc0110 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Parent Window</title>
<!-- Use the angular js we use at this moment -->
<script
src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js"
integrity="sha512-CiKQCmN86Y1I8Ewkt2gGnSNmsiVrS9Ez5MoudCBhTiBJScg+GjA9OlKdaeI0IuxdCl43Fs5x5zpeew2hfOatOA=="
crossorigin="anonymous"
></script>
</head>
<body ng-app="mainApp" ng-controller="c1">
<h1>Parent Window</h1>
<button ng-click="toggleIframe()">Toggle iFrame</button>
<button ng-click="toggleMessages()">Toggle Messages</button>
<p>
Send Message:
<button id="message_button" ng-click="sendToChild()">
Hi there iframe
</button>
</p>
<div ng-if="showMessages">
<p>Got Message:</p>
<p ng-repeat="m in messages">{{m.data}}</p>
</div>
<br />
<angular9 ng-if="showAngular9" />
<script>
var mainApp = angular.module("mainApp", []);
mainApp.controller("c1", [
"$scope",
"$http",
function ($scope, $http) {
// view model
$scope.messages = [];
$scope.showMessages = false;
$scope.showAngular9 = true;
$scope.toggleIframe = () => {
$scope.showAngular9 = !$scope.showAngular9;
$scope.messages = [];
};
$scope.toggleMessages = () => {
$scope.showMessages = !$scope.showMessages;
$scope.messages = [];
};
// angular convention scope fields
$scope.ang9Data = "Initialization Data"; // Angular 9 props
$scope.ang9Loaded = (sendMessage) => {
console.log(
"Parent Controller: Angular 9 has loaded. Now button can send messages"
);
$scope.sendToChild = () => {
sendMessage("Click!");
};
};
$scope.ang9Listen = (payload) => {
if ($scope.showMessages) {
$scope.messages.push({
data: "Parent Controller iframe message: " + payload,
});
}
};
},
]);
mainApp.directive("angular9", function () {
var directive = {
restrict: "E", // element directive
scope: false, // same scope as parent
template:
"<iframe src='http://localhost:4200/' id='the_iframe' style='width: 80%; height: 750px;'></iframe>",
};
// addEventListener support for IE8
function bindEvent(element, eventName, eventHandler) {
if (element.addEventListener) {
element.addEventListener(eventName, eventHandler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + eventName, eventHandler);
}
}
const createObservable = () => {
let listeners = [];
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter((l) => l !== listener);
};
};
const notify = (e) => {
listeners.forEach((element) => {
element(e);
});
};
return { subscribe, notify };
};
//compile is called during application initialization. AngularJS calls it once when html page is loaded.
directive.compile = function (element, attributes) {
const observable = createObservable();
bindEvent(window, "message", function (e) {
observable.notify(e);
});
// Only executed once in the app, no unsubscribe needed. Convinient way of logging all iframes messages
observable.subscribe((e) =>
console.log(
"Parent Logging iframe message: " + JSON.stringify(e.data)
)
);
//linkFunction is linked with each element with scope to get the element specific data.
var linkFunction = function ($scope, element, attributes) {
console.log("Parent: subscribe to iframe");
// Make sure you are sending a string
var sendMessage = (msg, channel = "*") => {
var objMsg = null;
if (typeof msg !== "string" && !(msg instanceof String)) {
objMsg = msg;
} else {
objMsg = { type: "text", text: msg };
}
const { contentWindow } = element[0].firstChild;
if (contentWindow != null) {
contentWindow.postMessage(objMsg, channel);
}
};
var unsubscribe = observable.subscribe((e) => {
if (e.data.type === "init") {
if ($scope.ang9Loaded) $scope.ang9Loaded(sendMessage);
if ($scope.ang9Data) sendMessage($scope.ang9Data);
observable.subscribe((e) => {
// $apply is needed to notify ui changes in angular js correctly
$scope.$apply(() => $scope.ang9Listen(e.data.text));
});
}
});
$scope.$on("$destroy", function () {
console.log("Parent: unsubscribe to iframe");
unsubscribe();
});
};
return linkFunction;
};
return directive;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment