inside my index.ejs i inserted an Iframe Tag to embed another document within the current document. Inside this Iframe i have a Form.
<iframe
src="purchase/form.html" scrolling="yes" id="purchase"
style="min-width:280px;width:100%;height:400px;border:none;"
frameborder="none"
allowTransparency="true" >
</iframe>
Inside this Form i want to target a Button with the class of stripe_button and the code looks like this
<button type="submit" class="btn btn-primary btn-lg stripe_button" style="z-index: 1;">
<span class="fa fa-credit-card-alt" aria-hidden="true"></span>
Pay
</button>
Doing this with the following Javascript code
// target iframe inside index.ejs
var iframe = document.getElementById('purchase')
// get iframe content
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
// targeting class and awaiting click event to run function
var stripe = innerDoc.getElementsByClassName('stripe_button')
for (var i = 0; i < stripe.length; i++) {
var stripe_button = stripe[i]
stripe_button.addEventListener('click', purchaseClicked)
}
the whole code is inside my ready function
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded', ready)
} else {
ready()
If i try to run this i get Failed to load resource: the server responded with a status of 404 (Not Found)
and i assume it's because im trying to submit a form on localhost and that makes sense so far also tells me that the click event is working.
But if i delete type="submit" from the button and refresh nothing happens although the
purchaseClicked function should get into work.
The purchaseClicked function looks like this
function purchaseClicked() {
var priceElement = document.getElementsByClassName('zahl')[0]
var price = parseFloat(priceElement.innerText.replace('$', '')) * 100
updateCartTotal()
stripeHandler.open({
amount: price
})
}
basically it calls stripe popup payment.
And i know that this works if i would assign the button from within my index.ejs file
for example: document.getElementsByClassName('checkout_button')[0].addEventListener('click', purchaseClicked)
I assume it has something to do with the click event.
Same Domain. Im aware of CROSS.
wrapping this function into a entire new function
function stripe() {
// target iframe inside index.ejs
var iframe = document.getElementById('purchase')
// get iframe content
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
// targeting class and awaiting click event to run function
var stripe = innerDoc.getElementsByClassName('stripe_button')
for (var i = 0; i < stripe.length; i++) {
var stripe_button = stripe[i]
stripe_button.addEventListener('click', purchaseClicked)
}
}
and calling it inside iframe
parent.function()
solved it.
Related
So I have this piece of code where the form is hidden until I click on the element. If I'm in that page (profile.php) it shows the form and scrolls down to it but if I'm not on that page (e.g: index.php) it goes to thatpage(profile.php) but doesn't show the form and doesn't scroll down to it until I click again on that element (which it is in the menu)
So here is my html code:
<a id='showForm'>Apply</a>
<div class="formL" style="display:none">
//code
</div>
and here's my script:
<script>
$('#showForm').click(function() {
let currentURL = $(location).attr("href");
let redirectURL = "http://127.0.0.1/dealaim/profile.php#formL"
if (currentURL !== redirectURL) {
$(location).attr("href", redirectURL);
var formL = $('.formL').show();
document.documentElement.scrollTop = formL[0].offsetTop;
} else {
var formL = $('.formL').show();
document.documentElement.scrollTop = formL[0].offsetTop;
}
</script>
The code after your redirect won't do anything; that code needs to run on the page you redirect to, not the page doing the redirect.
Once the redirect takes place, it's a question of passing along some info that the page can receive and use to automatically invoke the function. So:
$('#showForm').click(function() {
let currentURL = location.href;
let redirectURL = "http://127.0.0.1/dealaim/profile.php?showForm=1"
if (currentURL !== redirectURL)
location = redirectURL;
else {
let formL = $('.formL').show();
document.documentElement.scrollTop = formL[0].offsetTop;
}
});
if (location.href.includes('showForm=1') $('#showForm').click();
Note also there's no point at all in doing $(location).attr('href') - you just unnecessarily invoke jQuery and wrap what is a simple object-and-property combo in its API. Just use location.href.
I'm trying to setup a send event from a iframe originated on my domain and placed on other domain (not mine). I placed the analytics code on the iframe.
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX-XX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXX-XX',{ 'anonymize_ip': true });
</script>
Bellow that analytics code (with the UA-XXXXXXXX-XX from my parentdomain.com), I do a check to see if the iframe is not on my parentdomain.com and then, I set the tracker attribute to the div id ads_close:
<script>
ref = document.referrer;
whitelist = ["parentdomain.com"];
match = false;
for( var i = whitelist.length - 1; i >= 0; i-- ) {
if( ref.indexOf( whitelist[ i ] ) > -1 ) { match = true; }
}
// If is not the parent domain, then add the onClick atributte to the ID "ads_close"
if( ! match ) {
refer = document.referrer;
var str1 ="gtag(\'event\', \'External\', {\'event_category\': \'yes\',\'event_label\': ";
var str2 = "'";
var str3 = refer;
var str4 = "'";
var str5 = "});";
var tracker = str1.concat(str2) + str3 + str4 + str5;
ads_close.setAttribute("onClick", tracker);
}
</script>
The above code renders this way, IF NOT, on parentdomain.com:
<div class="adspop_close" id="adspop_close" onclick="gtag('event', 'Externos', {'event_category': 'yes','event_label': 'https://www.theotherdomain.com/post/'});"></div>
The problem:
Every time i click on the the div with the ID adspop_close, I cannot see the event on my parentdomain.com google analytics account...
The question:
What am'I doing wrong?
If you try to track data from the iframe itself it will appear as if the interaction is happening on another domain in another session, which is what I think you're trying to avoid. If you want to track interactions in an iframe and act as if they were part of the parent container then the best way is by using postMessage to communicate the event to the parent, where it can be handled naturally. The containing page does not have script access to the iframe for security reasons, but the iframe can send communicate to the containing page via postMessage.
solution 1
The Google Development Guide shows us an approach for this cross-domain interaction (scroll down to the IFRAME section).
To link the interactions into the same session you need to share client id's. Unortunately, iframes typically initalize with the HTML of the page, long before google tracking has the client ID ready. So we can't just pass it on load, but need to wait for everything and then use postMessage.
Here's the containing page code example:
<iframe id="destination-frame" src="https://destination.com"></iframe>
<script>
ga('create', 'UA-XXXXX-Y', 'auto');
ga(function(tracker) {
// Gets the client ID of the default tracker.
var clientId = tracker.get('clientId');
// Gets a reference to the window object of the destionation iframe.
var frameWindow = document.getElementById('destination-frame').contentWindow;
// Sends the client ID to the window inside the destination frame.
frameWindow.postMessage(clientId, 'https://destination.com');
});
</script>
And here's the listener that would be in the iframe:
window.addEventListener('message', function(event) {
// Ignores messages from untrusted domains.
if (event.origin != 'https://destination.com') return;
ga('create', 'UA-XXXXX-Y', 'auto', {
clientId: event.data
});
});
That page also has some extra logic to handle the situation where a client id never comes through postMessage. If you need to pass through the 'UA' string as well and wait to initialize gtag in the iframe completely, that's doable as well. Once you recieve the data you need, initialize gtag and track away. You won't need to rewrite any DOM.
solution 2
You can invert the logic of the postMessage communication instead. Rather than doing any tracking in the iframe at all, you can set up any events to trigger a postMessage instead, passing the information like category, action, and label up to the containing page. In the containing page you would add a listener for the postMessage and handle it by triggering a gtag event.
For instance, from the iframe:
<script>
try {
var postObject = JSON.stringify({
event: 'iframeClickEvent',
category: 'someCategory',
action: 'someAction',
label: 'someLabel'
});
parent.postMessage(postObject, 'https://www.YOURWEBSITE.com');
} catch(e) {
window.console && window.console.log(e);
}
</script>
and the containing page:
window.addEventListener('message', function(message) {
try{
var data = JSON.parse(message.data);
var dataLayer = window.dataLayer || (window.dataLayer = []);
if (data.event === 'iframeClickEvent') {
dataLayer.push({ 'event': 'someEvent', .... });
}
} catch(e){}
});
I currently have a button. When it's clicked I execute a javascript code.
var openAppBtn = document.getElementById("openAppBtn");
openAppBtn.onclick = function () {
var app = {
launchApp: function () {
window.location.replace("testappscheme://")
}
};
app.launchApp();
};
<a id="openAppBtn" class="btn" href="">Open KWCP App</a>
when I execute this bit of code on iOS, the page does a refresh if the app is not installed. May I ask how do I attempt to open the app without the page redirecting.
You could use an iframe to trigger the app intent. Example code for triggering the intent on the page-load for example. Just put it inside your click function.
<script type="text/javascript" charset="utf-8">
var frame = document.createElement('iframe');
frame.src = 'testappscheme:/' + window.location.pathname + window.location.search;
frame.style.display = 'none';
document.body.appendChild(frame);
// the following is optional, just to avoid an unnecessary iframe on the page
setTimeout(function() { document.body.removeChild(frame); }, 4);
</script>
Simply by clicking the button, add an iframe to your page with the schema-url.
I am trying to access an div (or here a tr tag) on which i want to append a button . But i am unable to access the tr tag because its loading after sometime and is not present in the DOM at that moment and getting error .
how to access a tag after loading something on the DOM
<script>
var btn = document.getElementById('btnn');
var tab = document.getElementsByClassName("scope")[0];
tab.append(btn)
</script>
I think your document.getElementById code should only be executed after everyting has been loaded. You could add an "load" Eventlistener and put your code inside it.
window.addEventListener("load", function(){
var btn = document.getElementById('btnn');
var tab = document.getElementsByClassName("scope")[0];
tab.append(btn)
});
By the way: I always use "defer" for my includes, like this:
<script src="{{ asset('/general/js/local.js') }}" defer></script>
This makes sure the "load" event will only be triggered after all includes have been loaded.
You could watch the DOM using the MutationObserver API. If the element you're observing is added, you could then apply your other code (e.g., append a button).
Basic Example:
let watchDOM = (function(){
let mo = window.MutationObserver;
return function(obj, callback){
if (!obj || !obj.nodeType === 1) {
return;
}
if (mo) {
let obs = new mo(function(mutations, observer) {
callback(mutations);
});
obs.observe(obj, { childList:true, subtree:true });
}
else if (window.addEventListener){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
watchDOM(document.body, function(e) {
// This will notify you if a new DIV is added.
if (e[0].addedNodes[0].tagName === "DIV") {
// If the DIV is added, you can then take some action here.
// For example, you could append your button here.
console.log("div added");
}
});
// This adds a new DIV after 3 seconds of running the script
setTimeout(function() {
let newDiv = document.createElement("div");
document.body.appendChild(newDiv);
}, 3000);
Is this DIV getting created in the response of an AJAX call. If that is the case then you need to call you your button appending logic once the response of AJAX call has been received.
OR use this:
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
// - Code to execute when all DOM content is loaded.
// - including fonts, images, etc.
});
</script>
I wrote a script that lets me delete all iFrames from a page by pressing a button:
window.addEventListener('load', function() {
var addButton = document.createElement("BUTTON");
addButton.innerHTML = "DELETE iFRAMES";
addButton.onclick = removeAllIFrames;
document.body.appendChild(addButton);
});
function removeAllIFrames() {
var iFrames = document.getElementsByTagName("iFrame");
for (var frame of iFrames) {
frame.parentNode.removeChild(frame);
}
}
While this works, I was wondering if it was possible to listen for iFrame insertions and just delete them as they appear on the page. Is there some sort of window.listenToElementInsertionByTag() method so I can automate this? Otherwise I could just use a setInterval() and execute the removeAllIFrames() method on an interval.