<!DOCTYPE html> <html> <head> <title>pmmain.local</title> <style> .hide { display: none; } pre { border: 1px solid black; } </style> <script type="text/javascript" src="//pmmain.local:8890/PM.js"></script> <script> /* This webpage hosted at http://pmmain.local:8888/index.html * will host the "parent website" for the "responder page" at pminner.local:8889. * It essentially accesses a pure javascript API for authorized domains. * Multiple domains can be called, allowing for a Service-oriented architecture in JS. * * This website uses PM.js to create a hidden iframe to the responder page. This * page creates a listener, waits for the other domain to tell it that it's ready for communication, * then sends requests. */ // You should preload URLs until you're ready to use them. // This vastly improves the speed for mobile devices, since their request times // may take significantly longer than desktops and laptop devices. // // Note: These URLs won't work, but they will produce a friendly error message in the console // after a few seconds. var iframes = PM.preloadUrls({ "BadUrlTest1":"http://badurl.local/test.html?test=true", "BadUrlTest2":"http://badurl.local/test2.html" }); // You can then call PM like so: PM.postMessage("BadUrlTest1", // iframe handle, from above preloadUrls call "testaction", // action to execute on google.com/test.html (not a real webpage) {my:"test", test:"is bad"}, // some data to send function(){ // callback function or listener name console.log("Couldn't load http://www.google.com/test.html?test=true because it's a bad URL. The page doesn't exist."); } ); // What if you don't want to worry about preloading URLs? // Fine. Just call it like this: PM.postMessage("test3", // new handle to be registered "testaction", // action to execute {my:"test", test:"is good"}, // data to send null, //callback function not defined here "http://pminner.local:8889/index.html" // webpage for otherdomain.com ); // Some people might want to execute a function when the request is complete with the result of the action. // The callback parameter allows data from the other domain's action to be passed into a callback function. // Note: in this example we only need the handle, not the URL because we've already registered the domain. // First, let's register a listener function called "mycallback" PM.registerListener("mycallback", function(data){ console.log(data) }); // When the postMessage request returns the data, it will execute the "mycallback" function. PM.postMessage("test3", // handle "returntest", // action to execute {my:"test", test:"is good"}, // data to send "mycallback" // callback function or listener name ); // That's too much work! Show me something easier! // Ok, you don't really have to register callbacks, just pass the function in and // we'll take care of it. PM.postMessage("test3", // handle "returntest", // action to execute {my:"test", test:"is good"}, // data to send function(data){ // callback function or listener name console.log(data) } ); //these functions are for the user account API. function showLogin(){ document.getElementById("login").style.display = "block"; document.getElementById("edit").style.display = "none"; document.getElementById("accountInfo").style.display = "none"; } function showRegisterAccount(){ document.getElementById("login").style.display = "none"; document.getElementById("edit").style.display = "block"; document.getElementById("accountInfo").style.display = "none"; } function showEditAccount(){ var usernameElem = document.editForm.username; var displayNameElem = document.editForm.displayName; PM.postMessage("test3", // handle "getAccount", // action to execute null, function(accountInfo){ usernameElem.value = accountInfo.data.username || ""; displayNameElem.value = accountInfo.data.displayName || ""; } ); document.getElementById("login").style.display = "none"; document.getElementById("edit").style.display = "block"; document.getElementById("accountInfo").style.display = "none"; } function login(event){ event.preventDefault(); var formData = {}; for(var i = 0; i < document.loginForm.length; i++){ if(document.loginForm[i].tagName === "INPUT"){ formData[document.loginForm[i].name] = document.loginForm[i].value; } } PM.postMessage("test3", // handle "login", // action to execute formData, function(accountInfo){ if(accountInfo){ console.log("login callback", accountInfo); document.getElementById("accountInfo").innerHTML = JSON.stringify(accountInfo, undefined, 2); document.getElementById("accountInfo").style.display = "block"; } } ); return false; } function editAccount(event){ event.preventDefault(); var formData = {}; for(var i = 0; i < document.editForm.length; i++){ if(document.editForm[i].tagName === "INPUT"){ formData[document.editForm[i].name] = document.editForm[i].value; } } PM.postMessage("test3", // handle "editAccount", // action to execute formData, function(accountInfo){ console.log("----editAccount2 outer", accountInfo); if(accountInfo){ document.getElementById("edit").style.display = "none"; document.editForm.username.value = null; document.editForm.displayName.value = null; document.editForm.password.value = null; } } ); return false; } function deleteAccount(){ PM.postMessage("test3", // handle "deleteAccount", // action to execute null, function(accountDeleted){ if(accountDeleted){ console.log("Account deleted! outer"); } } ); } function getAccountInfo(){ console.log("----getAccountInfo", PM._registeredListeners, Object.keys(PM._registeredListeners)); PM.postMessage("test3", // handle "getAccount", // action to execute null, //no data function(accountInfo){ console.log('---getAccount outer'); document.getElementById("accountInfo").innerHTML = JSON.stringify(accountInfo, undefined, 2); document.getElementById("accountInfo").style.display = "block"; } ); } </script> </head> <body> <nav> <h1>Examples</h1> <a href="index.html">Resize iframe</a> </nav> <h1>User Account API</h1> <p>Use the buttons below to test the API registered on the other domain. *All information is stored in sessionStorage and is kept on your computer. There is no actual registration or login process external to your own system.</p> <button onclick="showLogin()">Login</button> <button onclick="showRegisterAccount()">Register</button> <button onclick="showEditAccount()">Edit Account</button> <button onclick="deleteAccount()">Delete Account</button> <button onclick="getAccountInfo()">Get Account Info</button> <div id="login" class="hide"> <form name="loginForm" onsubmit="return login(event)"> <p> <label>Username: <input type="text" name="username" /></label> </p> <p> <label>Password: <input type="text" name="password" /></label> </p> <p> <button>Login</button> </p> </form> </div> <div id="edit" class="hide"> <form name="editForm" onsubmit="return editAccount(event)"> <p> <label>Username: <input type="text" name="username" /></label> </p> <p> <label>Password: <input type="text" name="password" /></label> </p> <p> <label>DisplayName: <input type="text" name="displayName" /></label> </p> <p> <button>Submit</button> </p> </form> </div> <h2>Account Info:</h2> <pre id="accountInfo"></pre> <p>There is an iframe shown below. This was manually created in the HTML, but you can use PM.preloadUrls instead. This is showing how you can use existing iframes with PM too, but PM.js is smart enough to create them on its own.</p> <p>Be sure to check the console to see some messages from this iframe.</p> <iframe src="http://pminner.local:8889/index.html"> </body> </html>