iframe won't scroll unless reopened - javascript

Currently I'm working on a widget which lives in an iframe on my page. I have the option for visitors to send me a message through a contact form inside the iframe (which is longer than the iframe, and so needs to scroll), however, when using Chrome on iOS8, the message form doesn't scroll unless i close and reopen the widget. Has anyone else come across this, or know what could be causing it?
The code that dictates the scrolling of the iframe is as follows:
frameDoc.body.firstChild.setAttribute(
'style',
['width: 100%',
'height: 100%',
'overflow-x: hidden',
'overflow-y: auto !important',
'-webkit-overflow-scrolling: touch !important'].join(';')
);
Ok new problem. When i open the iframe, the'-webkit-overflow-scrolling: touch' style is added, but when i close it and reopen, the style disappears. If i close it and reopen it AGAIN, the style is added again. My code is as follows:
if (
existingStyle.indexOf('-webkit-overflow-scrolling') === -1) {
frameFirstChild.setAttribute('style',
`${existingStyle};-webkit-overflow-scrolling: touch;`);
}
There is a setTimeout function wrapped around this statement, however changing the timeout does has no effect on whether the style is added or not. also my var definitions are as follows:
var frameFirstChild = this.getDOMNode().contentDocument.body.firstChild,
existingStyle = frameFirstChild.getAttribute('style');

Worked it out. Had to move
existingStyle = frameFirstChild.getAttribute('style'); to inside before the if statement, while still wrapped inside setTimeout()

Related

Is it possible to keep a popup hidden until some code is executed?

So, I have this extension, and it should show a custom popup on the page when the icon is clicked, and by "custom popup", I mean, something rendered inside an <iframe> and injected in the page dom itself, not an "traditional extension popup", but the problem is that in some pages i'm not able to inject a content-script, in those cases, I would want to display the content in the "traditional extension popup".
I got it to work, but it's not the most elegant of a solution, here's how I'm doing it
The popup.html has no content in it's <body>, and it imports a script.
This script tries to send a message to the content script running in the page, if the message is successfully, the popup will close itself, and the content script will handle the render on the page
If the message could not be sent then it tries to inject the script on the page, if the injection works, then the message is sent again, if it doesn't, then we are on a page that does not allow injection, in that case, we simply render the content to the popup's body (i'm using Svelte here)
browser.tabs.query({active: true, currentWindow: true}).then(tabs => {
const tab = tabs[0];
browser.tabs.sendMessage(tab.id, {action: "toggle"}).then(() => {
window.close();
}).catch(() => {
injectScript(tab).then(() => {
browser.tabs.sendMessage(tab.id, {action: "toggle"}).then(() => {
window.close();
});
}).catch(() => {
document.body.style.width="400px";
document.documentElement.style.height="580px";
new App({
target: document.body,
});
});
});
});
The thing is, most of the time, this process is basically instantaneous, you just click the icon, and the custom popup shows up, but sometimes, it takes a little longer (maybe 1 sec?), and in that time, you can see the "traditional popup" on it's minimum size (maybe something around 32x32? It's a really small square)
What I would like is to keep the popup hidden until my code "decided" wheter it's possible or not to inject the content in the page.
What I've tried and does not work:
Setting width and/or height of the and/or tags to 0px
Setting display:none and/or visibility: hidden on and/or tags
Is there any way to do what I'm looking for?
EDIT:
Here's an image so you can better understand what I'm talking about, this is the "square":
Sometimes you can't even see it, sometimes it just blinks, and sometimes it takes a bit longer to go away, it depends on the pc I think
I would use a layer in this case. A layer can be done using CSS, can contain all of the proper formatting and text, and can be shown or hidden whenever you want not affecting any of the other text around it due to it being on another layer. I'm unsure if this will solve your problem because I don't really know the context of the program you are creating and what you are trying to accomplish.

plupload - upload button works only if click is triggered programatically

I am using plupload 1.5.7. I have two buttons on page:
First one (Add new attachment) was used as browse_button in plupload configuration. When I click it, it doesn't work. Click event is executed, but file browser is not opened. But there is second button (Trigger add new attachment click), which only does this:
$('#TriggerAddNewAttachmentClickButton').click(function() {
$("#AddNewAttachmentButton").click();
})
So it only triggers click of the first button. It works fine. Clicking it opens file browser.
How is this possible? This behavior is consistent between Firefox, Chrome and Internet Explorer.
Obviously this is security related, because plupload uses tricks to hide input, but second method is not safer. I can't reproduce this issue in jsfiddle, it exists only in specific context, but maybe there is someone, who ecountered similar behaviour.
I got a similar issue with plupload. I digged into this issue for hours, and finally I find the reason. As #jbl said:
I guess I remember I had this kind of problem when the container was not visible upon plupload initialization. Could it be the same problem ?
The way of plupload working is as following:
Remember you need to set a browse_button? Actually the plupload will create an input[type="file"] for each browse_button. In normal situation, the size and position of the input[type="file"] will be the same with the browse_button exactly. So when you click the browse_button, it's not the button trigger a file chooser dialog popping up, it's the input[type="file"].
But when you set the browse_button container something like: display:none(we say, inactive), and after that even you set back the display:block(we say, active), the width and height of the input[type="file"]'s parent container would be zero some time.
My quick fix solution for this issue is as following:
I measure the position and size of the browse_button when change the state of the container from inactive to active. Then I'll manually set the position and size to the hidden input[type="file"];
Following is some sample code:
var $btn = $currPanel.find(".browse_button");
var w = $btn.outerWidth();
var h = $btn.outerHeight();
var position = $btn.position();
var $hiddenInputDiv = $currPanel.find(".moxie-shim");
$hiddenInputDiv.height(h);
$hiddenInputDiv.width(w);
$hiddenInputDiv.css(
{
top: $btn.css("margin-top"),
left: position.left
});

How To Trigger Fancybox When User Reaches Certain Div (On Scrolling)

quick question:
1) I have got the standard Fancybox (V2) setup working and I want it to fire the modal when the user is reading the page and then reaches a certain div (or any other element).
2) So it's not a 'delay', its when the user reaches a certain part of the page.
Can someone throw some coding light on how to do this please? :)
(Note: I AM NOT a programmer, but can handle mediocore js/html/css...)
The easiest way is to check the scroll height versus the height of the element you wish to trigger, then simulate a click on the Fancybox link you want to open.
UPDATE: This fiddle should give you an idea how to do it. http://jsfiddle.net/eKF4f/2/. It is not the most complete example, but should give you a starting point.
This is the part that does the work
$(document).scroll(function () {
if($(document).scrollTop() >= $('#box').offset().top && !fired)
{
$.fancybox.open([
{
href : 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title : '1st title'
}]);
}
});
NOTE: As far as UX is concerned, this is generally bad practice. Unless you have a good reason to open a modal, you should not block page content unless the user takes an action that triggers the modal.

Twitter Bootstrap Modal scrolling the page up on show

Clicking on a link which triggers a Twitter Bootstrap Modal to pop up is causing the browser to scroll up the page. This behavior is only occurring in Chrome.
Here is a demonstration page:
http://www.turizmburosu.com/test2.aspx
The page has 600 rows of links, causing the page body to exceed window height. If any of these links is clicked, it displays the modal dialog. When in Chrome, clicking any of the links below the initial view will cause the background page to scroll up (not always entirely to the top).
I am use the following function to trigger the display of the Modal:
function test(id, imp) {
$("#modalLabel").html("Header");
$("#modalBody").html("Body");
$("#myModal").modal("show");
}
and the links are of the form:
Test Link ###
I am seeing this behavior in Chrome 22.0.1229.94 m.
Any suggestions/ideas as to why this is happening and how to prevent it?
Additional Example
This can be recreated on the Twitter Bootstrap documentation page for the Modal plugin.
Once on the page, simply override the existing data-api to use the JavaScript api instead:
$('#modals a[data-toggle="modal"]').on('click',
function(e) {
$('#myModal').modal('toggle');
return false
});
Now, if the Launch Demo Modal button is clicked, the page will scroll up when the modal is shown.
Again, this is using Chrome.
Fixed (10/29/2012)
This issue has been fixed since Bootstrap v2.2.0. See commit e24b46... for details.
(original answer)
This is due to a bug in the implementation of the Twitter Bootstrap Modal (as of 2.1.1). The root of the problem is that the focus is set to the modal prior to it completing its transition. This will only occur under the condition that
the browser supports CSS transitions (and you are using bootstrap-transition.js);
the modal has the class fade; and
when focus is set to an element outside the current view, the browser will scroll to move it into view (e.g., Chrome, Safari).
It should be noted that this affects both the Data API (markup-based) and the Programmatic API (JS-based). However, the reason it is more noticeable when taking the programmatic approach is because, unlike the Data API, it does not automatically restore focus to the triggering element, and, hence, does not scroll the view back down when the modal is hidden.
More info is available on the Twitter Bootstrap repo under Issue #5336: Modal Scrolls Background Content.
A fix has been merged into the 2.1.2-wip branch, which should be up for release any day now.
Here is a demo using the patch bootstrap-modal.js:
JSFiddle
Same problem. It is caused by "#" in and the anchor is doing to scroll.
I fixed that by deleting the anchor tag and place this:
<span onclick="$('#umisteni_modal').modal('show');" style="cursor:pointer;">Změnit místo dodání</span>
I had a similar issue on my site, which was caused by another jquery plugin (sidr).
When the sidebar was present and I opened a modal window, I would be sent back to top.
In jquery.sidr.js I changed line 102-106 from:
// Prepare page if container is body
if($body.is('body')){
scrollTop = $html.scrollTop();
$html.css('overflow-x', 'hidden').scrollTop(scrollTop);
}
To:
// Prepare page if container is body
if($body.is('body') && !$('#modal').hasClass('in')){
scrollTop = $html.scrollTop();
$html.css('overflow-x', 'hidden').scrollTop(scrollTop);
}
If you are using this plugin along with twitter bootstrap's modal, maybe this can help you.
I had the same problem because of these lines of CSS which were thought to permantly display scrollbars in the browser. Removing the two lines solved the problem:
html,
body {
min-height: 100%;
height: 101%;
}
to bring the focus back on close
var triggerOffset=0;
$('.modal').on('show.bs.modal', function() {
triggerOffset=$(window).scrollTop();
});
$('.modal').on('hidden.bs.modal', function() {
var animationTime=1;
$('html, body').animate({
scrollTop: (triggerOffset)
}, animationTime);
});
I had been having this issue for so long but my solution was to remove href from the anchor tag
i.e.
<a onclick="test();return false;">Test Link ###</a>
I get no jump now
Hope this helps someone in the future

Setting viewScope onLoad and onResize

I have used the '#media only screen' in my CSS to determine how and what information should be shown depending on the users screen size. I have a class called panelContainer which is set to display when the screen is greater than 767px, and a class called mobileContainer which displays when the screen is less than that.
I have a couple of custom controls, one that contains the standard form layout and another that contains the mobile device form layout. Originally I placed a div around each with the appropriate styleClass. The problem with it this way was that although only one form is visible, they were both loaded so this caused save issues.
<xp:div id="panelContainer" styleClass="panelContainer">
<xc:content_sCompany></xc:content_sCompany>
</xp:div>
<xp:div id="mobileContainer" styleClass="mobileContainer">
<xc:content_iCompany></xc:content_iCompany>
</xp:div>
I have since added a div to my Xpage with the styleClass of panelContainer, I then added onLoad and onResize events which return the style.display of the div, these should then write the result to a viewScope. But I found it would only write onLoad and although the function was being called onResize it wouldn't change the viewScope variable.
<xp:scriptBlock id="scriptBlock1" type="text/javascript">
<xp:this.value>
<![CDATA[var init = function() {
obj=document.getElementById('formType');
if(getStyleDisplay(obj)=="none"){
formType='#{javascript:viewScope.put("formFormat","mobile");}';
}else{
formType='#{javascript:viewScope.put("formFormat","standard")}';
}
}
dojo.addOnLoad(init);
dojo.connect(window,"onresize",init);
function getStyleDisplay(obj) {
if(obj.currentStyle) { // IE – Opera
return obj.currentStyle.display;
} else { // firefox
return getComputedStyle(obj,'').getPropertyValue('display');
}
}]]>
</xp:this.value>
</xp:scriptBlock>
<div id="formType" class="panelContainer"></div>
.....this viewScope variable is then used in the following way:
<xc:content_Company xp:key="ContentControl">
<xp:this.facets>
<xc:content_sCompany id="content_sCompany"
xp:key="standard">
</xc:content_sCompany>
<xc:content_iCompany id="content_iCompany"
xp:key="mobile">
</xc:content_iCompany>
</xp:this.facets>
</xc:content_Company>
.....extract from content_Company......
<xp:callback facetName="#{viewScope.formFormat}" id="cbkCompanyFormContent">
</xp:callback>
I feel this is the better way to achieve the result I need, as when I have tried it manually it does only load one of the forms and they work as expected.
I cannot see why the viewScope is not being set properly, it is always being set to 'standard', even if I shrink my page before loading the page. I did try writing the value to a Hidden Input, which worked but whenever I tried to access the value using getComponent("hiddenInput1").getValue() it would return null, even though I could see that value had been set when viewing in firebug.
Ok can you check (or tell me if you already have) through some console.log("") 's that the onResize is being called and the correct display is being pulled down etc.
next it may be firing the onResize but are you then partail refreshing the area which is using the viewScope?
Code example of this: (replace controlID with yours)
XSP.partialRefreshGet("controlID", {
onError: function() { console.log('Error'); }
});
I'm a little confused about what the purpose of using onResize is for ? if is to decide what to show whether on mobile or normal screen there are much more efficient ways of doing this.
Using the new redirect control in the latest release of the ExtLib on openNTF. It does exactly what the name suggests and redirects based on certain expressions. leaving you to drop it on a page and say if mobile (or whatever) redirect to this page.
Having a dummy default load page that checks the useragent string to see which page to load (having a separate mobile / fullscreen pages). This is what the teamroom template application that comes with the ExtLib does with its main.xsp and then this is set as the default launch option.
Or if you are trying to do something with whether the phone / tablet is on landscape or portrait you should be using the onOrientationChange event not onResize. check out this example (not the code in the question is what I'm pointing you too, he has a problem getting that to work in a webview):
how to handle javascript onorientationchange event inside uiwebview

Categories