Scrolling issues with ExtJS 5 app inside IFrame - javascript

Hy,
this is what my test page looks like:
The blue area is the parent page and the green area is an IFrame which runs an ExtJS application (simple viewport with a label inside).
If the site is executed on a touch device (IPad, Android Tablet etc) it's not possible to scroll the page by "wiping" on the IFrame (the green area). One has to wipe on the blue area to scroll the page.
This had been working correctly in ExtJS v4.2.1 (see links below).
Test-Sites:
https://skaface.leo.uberspace.de/ScrollTest/Ext510/ (not working as expected, using ExtJS v5.1.1)
https://skaface.leo.uberspace.de/ScrollTest/Ext421/ (working as expected, same code but using ExtJS v4.2.1)
The test code:
Parent site (index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body style="margin: 50px; background-color: blue;">
<iframe src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
</html>
IFrame (frame.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all-debug.css" />
<script type="text/javascript" src="https://extjs.cachefly.net/ext/gpl/5.1.0/build/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady(function() {
Ext.create('Ext.container.Viewport', {
style: { 'background-color': 'yellowgreen' },
layout: 'fit',
items: [{
xtype: 'label',
text: 'Ext version: ' + Ext.versions.extjs.version,
margin: 16
}]
});
});
</script>
</head>
<body>
</body>
</html>
I'd really appreciate a workaround for this since it practically makes my sites useless on mobile devices even though they had been working perfectly fine with ExtJS 4.2.1.
Thanks & best regards
Ps.: I've already posted a bug report in the sencha forums, but since I didn't get any help there until know, I'm also trying my luck on stackoverflow...

The behavious is weird , I have seen it before using niceScroll plugin , and many other plugins had also same issue with iframe , anyway check this workaround
I have used Hammer.js jQuery plugin to detect touch gestures on your iframe , if you find any issues concerning sensetivity ( as I dont know what constraints you are looking for ) , you can adjust hammer.js options found on their repo ( like pan threshold , pointers ..etc )
and the code is very simple :
<body id="mainbody" style="margin: 50px; background-color: blue;">
<iframe id="myframe" src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
<script>
var myBody
$('iframe').load(function(){
myBody=$(this).contents().find("body");
myBody.css({"height":"100%","overflow":"hidden"}).hammer({threshold:1}).bind("pan", myPanHandler);
});
function myPanHandler(ev)
{
$("#mainbody").scrollTop($("#mainbody").scrollTop()-ev.gesture.deltaY)
console.log(($("#mainbody").scrollTop()-ev.gesture.deltaY*0.5)+".."+$("#mainbody").scrollTop())
}
</script>

After a lot of digging around inside the framework, I finally found a solution which at least works for me and consists of 2 steps:
1) ExtJS sets the CSS property touch-action of the viewport (the base html element of the IFrame) and its body to the value none.
I've simply overwritten it with the value auto:
.x-viewport, .x-viewport > .x-body {
touch-action: auto;
}
2) The class Ext.container.Viewport calls Ext.plugin.Viewport.decorate(this); in it's creation callback, which adds a listener to the touchmove event of the viewport itself.
Everything that listener does is calling preventDefault(); of the event, which is the reason why scrolling doesn't work anymore on the parent page or the IFrame itself.
My fix simply removes the preventDefault() and instead returns false from the touchmove event handler to let the event bubble up the browser chain:
Ext.define('Cbn.overrides.container.Viewport', {
override: 'Ext.container.Viewport'
}, function() {
Ext.override(this, {
onRender: function() {
this.mon(Ext.getDoc(), {
touchmove: function(e) {
// e.preventDefault(); // Original ExtJS code
return false;
},
translate: false,
delegated: false
});
this.callParent(arguments);
}
});
});
I'm not quite sure if those 2 fixes have any negative implications but so far they seem to do the job for me.
One thing I did realize is that using components with the config scrollable: true inside the IFrame-App still makes problems but since I can avoid that pretty much everywhere it's no issue for me so far...
Working test-site: https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/
Edit:
Adjusted solution a little to not constantly throw unhandled JavaScript errors during touch-scrolling (see Error: Failed to execute 'dispatchEvent' on 'EventTarget')

Related

Have iframe load after user scrolls down page and it comes into viewport

I'd like an iframe to load only when the user scrolls down the page and it comes into the viewport. This has been answered (link below) but I'm not very good with javascript and I can't work out how to combine the 2 bits of code in the answer.
Can anyone help? It would be great if someone could combine the bits of javascript for me.
Charlie
Having iframe load after scrolling down on page
Here's what I did:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
title>FS checker test</title>
<style>
<!--
#iframe1 {
background-color: #ccc;
margin: 1800px 10px 10px 10px;
height: 500px;
width: 500px;
}
-->
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<iframe id="iframe1" frameborder="0" scrolling="no" src="about:blank" data-src="http://www.mets.com"></iframe>
<script>
if ($('#iframe1').visible(true)) {
var iframe=$('#iframe1');
if (iframe.data('src')){
iframe.prop('src', iframe.data('src')).data('src', false);
} else {
}
}
</script>
</body>
</html>
Your brackets are nested incorrectly. Indenting your code will make this sort of problem much easier to spot. Also make sure you have the browser developer tools open to the console, so you can see error messages.
This should work (provided you've also installed the jquery-visible library on the page):
if ($('#iframe1').visible(true)) {
var iframe=$('#iframe1');
if (iframe.data('src')){
iframe.prop('src', iframe.data('src')).data('src', false);
} else {
// or you could omit the 'else' clause, since it's not doing anything
}
}

Call composition ready of (edge animate) from javascript

I have a problem in html5 edge animate. I have created an animation using edge animate.
I would like to call composition ready of edge animate from outside. I tried calling using $.Edge.registerCompositionReadyHandler( compId, handlerFn, options ) , But it gave error ReferenceError: $ is not defined . I am not able to solve this and i did not find enough documentation about this. Can any one please help me.
my code looks like this
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<title>Untitled</title>
<!--Adobe Edge Runtime-->
<script type="text/javascript" charset="utf-8" src="teste1_edgePreload.js"></script>
<script type="text/javascript" src="teste1_resize.js"></script>
<style>
.edgeLoad-EDGE-1429726 { visibility:hidden; }
</style>
<!--Adobe Edge Runtime End-->
<script>
$.Edge.registerCompositionReadyHandler("EDGE-1429726",scaleStage) //SCALE STAGE IS INSIDE THE JAVASCRIPT fn teste1_resize.js
function mover(){
var stage = $.Edge.getComposition("EDGE-1429726").getStage();
console.log($("#Stage").height());
stage.mover();
}
</script>
</head>
<body style="margin:0;padding:0;">
<div id="Stage" class="EDGE-1429726">
<input type="button" value="Mover" onClick="mover();">
</div>
</body>
Thanks in ADVANCE
With Ena's help and little modification i was able to find an answer.
AdobeEdge.bootstrapCallback(function(compId) {
AdobeEdge.Symbol.bindElementAction(compId, 'stage', 'document', 'compositionReady', function(sym, e){
// composition is loaded, do stuff here
});
});
Instead of
$.Edge.registerCompositionReadyHandler
use
AdobeEdge.registerCompositionReadyHandler
Moreover, put your code inside this function:
AdobeEdge.bootstrapCallback(function(compId) {
// Register your handlers here
});
So you are sure the stage is loaded and you can register handlers in it.

JavaScript object properties are "sometimes" undefined

I am very confused.
I created the following script which is located at http://tapmeister.com/test/dom.html. For some unknown reason, tinymce.editors.ta1 and tinymce.editors[0] show up as undefined, and attempting to use a method under them results in an error. But when I inspect tinymce or tinymce.editors using FireBug, I see them in the DOM.
So, I create a jsfiddle http://jsfiddle.net/JWyWM/ to show the people on stackoverflow. But when I test it out, tinymce.editors.ta1 and tinymce.editors[0] are no longer undefined, and the methods work without error.
What is going on??? Maybe something to do with public/protected/private properties? How do I access methods such as tinymce.editors.ta1.hide()? Thank you!!!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title>Testing</title>
<script src="http://tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({selector: "textarea#ta1"});
tinymce.init({selector: "textarea#ta2"});
console.log(tinymce);
console.log(tinymce.editors);
console.log(tinymce.editors.ta1);
console.log(tinymce.editors[0]);
//tinymce.editors.ta1.hide();
//alert('pause');
//tinymce.editors.ta1.show();
</script>
</head>
<body>
<form>
<textarea id="ta1"></textarea>
<textarea id="ta2"></textarea>
</form>
</body>
</html>
TinyMCE doesn't do all of the setup work immediately when you call init. It provides a callback, setup, to tell you when the work is done.
So if you provide a setup callback, you can interact with the editor instance then.
Here's an example (I've also moved your scripts to the end, which is best practice regardless):
Live Example | Live Source
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
<title>Testing</title>
</head>
<body>
<form>
<textarea id="ta1"></textarea>
<textarea id="ta2"></textarea>
</form>
<script src="http://tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script type="text/javascript">
tinymce.init({
selector: "#ta1, #ta2",
setup: function(e) {
console.log("Editor " + e.id + " is ready");
}
});
</script>
</body>
</html>
Now, if you want to actually access the editor instance, bizarrely TinyMCE doesn't add it to tinymce.editors until after calling the setup function. But if you throw in a brief yield, you're all set. Here's the above with a changed setup function:
Live Copy | Live Source
setup: function(e) {
// Bizarrely, TinyMCE calls `setup` *before* adding
// the relevant editor to `tinymce.editors`,
// so we have to yield briefly
console.log("Editor " + e.id + " is ready");
if (e.id === "ta2") {
console.log("It's ta2, I'll hide it in a moment.");
setTimeout(function() {
tinymce.editors[e.id].hide();
}, 0);
}
}
So why did it work on jsFiddle? Well, jsFiddle has a truly brain dead surprising default setting, which is to put all of your script in a window#load callback function. window#load happens very late in the load process, after all external resources have been loaded. (You can see that in the jsFiddle UI, it's the second drop-down list on the left.) So apparently TinyMCE was completely ready at that point, where it isn't earlier in the cycle.
Side note: 99.9% of the time, there is absolutely no point in supplying a tag name with an id selector, e.g. textarea#ta1. id values are unique, so you don't have to qualify them unless you explicitly want to avoid matching an element that may sometimes have one tag name, or other times have another, which is a pretty unusual use case.
There's a large chance that your script is running before tinyMCE has actually loaded. It might be the case that it loads faster from your test site so that is why it works.
Use as a quick check.

JQuery Ascensor JS Plugin Not Working

I am trying to build a single-page scrolling website leveraging the Ascensor JQuery plugin, and am having a lot of trouble getting it setup correctly. The documentation at http://kirkas.ch/ascensor/ is helpful, but I still must be missing something. What I want is a simple 3-floor layout, top to bottom. It seems that the layout of my "building" gets generated correctly, but I am unable to move between the "levels." The arrow keys and my links don't move the page at all. Can I get a little help with my code? Any guidance is appreciated.
Thanks,
Brett
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ascensor Test</title>
<script src="jquery-1.9.1.js"></script>
<script src="jquery.scrollTo-1.4.3.1.js"></script>
<script src="jquery.ascensor.js"></script>
<script src="jquery.easing.1.3.js"></script>
<script>
$(document).ready(function()
{
$('#house').ascensor(
{
AscensorName:'ascensor',
ChildType:'div',
AscensorFloorName:'Home | Implementation | HTML',
Time:1000,
Easing:'easeInOutCubic',
WindowsOn:1,
Direction:'y',
AscensorMap:'1|1 & 2|1 & 3|1',
KeyNavigation: true,
Queued:false,
QueuedDirection:"x"
});
});
</script>
<style>
body
{
margin: 0;
padding: 0;
}
#house
{
overflow: hidden;
border: 5px solid black;
}
#navigation
{
z-index: 1000;
position: fixed;
top: 50px;
left: 50px;
}
#ascensorFloor1
{
background-color: orange;
}
</style>
</head>
<body>
<div id="navigation">
Floor 1
Floor 2
Floor 3
</div>
<div id="house">
<div>
Floor 1
</div>
<div>
Floor 2
</div>
<div>
Floor 3
</div>
</div>
</body>
</html>
The problem is not you, it is in "jquery-1.9.1.js".
I've tried to implement ascensor myself, and figured that the problem is that the plugin doesn't work with the last update from jQuery. The version originaly used 1.5.1. Check it out the jQuery in Git (https://github.com/seekvence/ascensor).
I've tried to find out why, but see no reason for that! Even tried to use the jQuery migrate plugin, but it didn't work as well!
The problem isn't the IDs, since it is the plugin that is generating them. So you shoudn't put them in your mark-up in the first place. I had the same problem as you and after going through a lot "on/off switching stuff", i found out that the problem was in the key navigation declaration. If you turn it to false, it starts working. Don't ask me why, but "KeyNavigation:false" gets the plugin to work. Which is a shame, since key navigation is one of the things i liked about the plugin... Anyway, try this and see if it works.
Easing:'easeInOutCubic' - don't work
Delete: Easing:'easeInOutCubic',
or: Easing:'linear',
..))

Strange behavior Shift-Key Safari - HTML/Javascript

As requested, I simplified the problem as much as possible.
What I am trying to do is adding a onmousemove event to an HTML element, in this case the box, that will call a function. The problem I have is that not only mouse movements trigger the event, but also keys like SHIFT, CTRL, ALT... do.
So, once the mouse is passed over the box for the first time and the alert window is closed, any of the keys I mentioned previously will also make a new alert window pop up.
I am working with Safari, I also tested this on Google Chrome and the result is also a weird behavior of the browser.
Here is the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3c.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<html xmlns="http://www.w3.org/1999/xhtml\" xml:lang="es" lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script>
window.onload = function() {
boxx = document.getElementById("box");
boxx.onmousemove = showMessage;
}
function showMessage() {
alert("hello");
}
</script>
</head>
<body>
<div id="box" style="width: 900px; height: 300px; border: 1px solid;"></div>
</body>
</html>
I really don't understand what is happening, hopefully someone can help me!

Categories

Resources