How to rotate a photo in FireMonkey TWebBrowser - javascript

I just tried FMX TWebBrowser in Delphi 10.3.3. I could not rotate a photo in img tag. The following page is working in Google Chrome. But it is not working in FireMonkey TWebBrowser of Delphi 10.3.3. What is wrong? Please someone help me!
<!DOCTYPE html>
<html>
<head>
<style>
img {
display: block;
width: 300px;
height: auto;
}
</style>
</head>
<body>
<button onclick="rotate();">Rotate 90 degrees</button>
<br />
<img src="20190228-1.JPG" id="theID" />
<script>
function rotate() {
var imgX=document.getElementById("theID");
imgX.style.transform = "rotate(90deg)";
imgX.style.display = "block";
}
</script>
</body>
</html>

I guess your target platform is Windows. TWebBrowser wraps IE based web browser control on Windows which displays pages in IE7 standard mode by default. This mode doesn't support CSS transformations. You have multiple options to workaround that.
Option 1: Use deprecated -ms-filter CSS property
-ms-filer or filter is Microsoft CSS extension to apply collection of graphic filters to an object. It also supports rotation:
imgX.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
Option 2: Force Egde standard mode via registry
This is also what TWebBrowser documentation encourages you to do on Windows platform. You basically need to enlist your application's EXE name under HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION either manually or programmatically as DWORD value that defines compatibility mode for your application. 11001 ($2AF9) is for IE11 edge mode. See Browser Emulation for further values. This setting will affect all pages loaded in any web browser control within your application.
Option 3: Use x-ua-compatible header to specify legacy mode
You should be able to achieve the same effect as in option 2 by injecting x-ua-compatible header via <meta> tag in your HTML:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="x-ua-compatible" content="IE=edge">
…
See Specifying legacy document modes for more information.
All of the above applies to Windows platform. Keep that in mind when picking from the options. Option 1 most likely won't work on other platforms.
While you're at it consider also separating JavaScript from CSS by leveraging CSS classes:
<style>
img {
display: block;
width: 300px;
height: auto;
}
.rotated {
transform: rotate(90deg);
}
</style>
…
<script>
function rotate() {
var imgX = document.getElementById("theID");
imgX.classList.toggle("rotated");
}
</script>

Related

Display an html iframe object inside an HTA application that uses javascript

I seek to run the following iframe object inside an HTA application and would like to later convert this to an exe file.
<iframe height="620" class="wizard-frame" style="max-width: 100% !important; border: 1px solid #dadada; overflow-y: hidden;" scrolling="no" src="https://www.rnv-online.de/timetable/?design=3&width=390&destination=" width="390"></iframe>
The appearance of the applicaiton should look as displayed here:
https://www.rnv-online.de/fahrtinfo/fahrplaene/fahrplanauskunfts-widget/
Here is the HTML Code I have come up with:
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<html>
<body>
<iframe
height="620"
class="wizard-frame"
style="max-width: 100% !important; border: 1px solid #dadada; overflow-y: hidden;" scrolling="no" src="https://www.rnv-online.de/timetable/?design=3&width=390&destination=" width="390"></iframe>
</body>
</html>
When I run the HTA file, I receive an error, which I can skip and get the asked widget. However, it is not interactive and I assume Javascript is an issue here. How can I get to work properly?
The page in the script does not work in IE 11 (e.g. calendar and clock do not work at all). If the page doesn't work in IE 11, it won't work in an HTA iframe either.
If you can find a page that actually works with IE 11, then the following information may be of use...
Even with the x-ua-compatible line in the HTA, the external site will get the mshta.exe default user agent header which is MSIE 7.0 by default. To ensure the external site gets an IE 11 header, apply this registry setting:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION]
"mshta.exe"=dword:00002af8
That will change the mshta.exe default mode from IE=7 to IE=11.
While this answer may appear to be a duplicate of other answers that refer to x-ua-compatible and the FEATURE_BROWSER_EMULATION registry value, I could not find any answers that made it clear that the x-ua-compatible setting does not carry over to the iframe. Here's a sample HTA script that demonstrates the issue:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=11">
</head>
<body>
<script>
window.resizeTo(850,650);
alert(document.documentMode + "\n\n" + window.navigator.userAgent);
</script>
<iframe width=800 height=550 src="https://gs.statcounter.com/detect"</iframe>
</body>
</html>

Detect viewport units (with modernizr or normal js) and serve appropriate stylesheet

I actually have an issue im trying to solve since 3 weeks. Im trying to test support for vw units and serve a seperate stylesheet when the browser doesnt support the unit
I read the modernizr tutorials and am familiar with modernizr css detects but testing for vh units (viewport relative units) is something I didnt find on the net.
So basically:
Scenario 1: Browser supports vw unit then serve stylesheet A.
Scenario 2: Browser doesnt support it then serve stylesheet B.
I did find out that there is a non-core detect called Modernizr.cssvwunit but I honestly have no idea where to start or how to use in in this context.
It would be great if you help me expand my knowledge. Also if it is not too laborious a jsfiddle with an example which I could study would be very helpful.
Sincerely,
Markus
Edit: why is it firing only the else statement? http://jsfiddle.net/5saCL/10
<script>
if (Modernizr.cssvwunit) {
alert("This browser supports VW Units!");
} else {
alert("This browser does not support VW Units!");
}
</script>
If you look at this tutorial http://www.developphp.com/view.php?tid=1253 you find out how to change CSS style with JavasSript.
You just need to edit little bit the script to match your requirements:
<!DOCTYPE html>
<html>
<head>
<link id="pagestyle" rel="stylesheet" type="text/css" href="default.css">
<script type="text/javascript">
if (Modernizr.cssvwunit) {
document.getElementById('pagestyle').setAttribute('href', "styleVW.css");
} else {
document.getElementById('pagestyle').setAttribute('href', "style.css");
}
</script>
</head>
<body>
<h2>Javascript Change StyleSheet Without Page Reload</h2>
<!-- no buttons needed -->
</body>
</html>
This should work.
Are you sure you want to load two different stylesheets?
Another option is to check "Add CSS Classes" in Modernizr. This way classes are added to the html element.
<html class="no-cssvhunit">
Then do this in your CSS:
.fullscreen {
height: 100vh;
}
.no-cssvhunit .fullscreen {
height: 100%;
}

Main web page in standard mode, iframe in compatibility mode: any issues?

We have some legacy HTML content which we must render in compatibility mode. The requirement comes from our customers who want their HTML-based reports (some of which were created back in IE6 days) to look and print exactly the same, regardless of the browser version or underlying technologies. At the same time, we want to use Standard Mode and HTML5 for the rest of our web app.
An obvious solution is to host the legacy content in an <iframe> in compatibility mode. The following appears to work cross-browser:
main.html (in standard mode):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<style type="text/css">
body {
font-family: Arial;
font-size: 9pt;
font-style: italic;
font-weight: bold;
}
</style>
<script type="text/javascript">
window.onload = function () {
info.firstChild.data = "document.compatMode: " + document.compatMode;
// test frame's HTML5 API: document.getSelection()
setInterval(function () {
var selection = document.getElementById("contentFrame").contentDocument.getSelection();
var selectedNode = selection.focusNode;
if (selectedNode)
info2.firstChild.data = "Selected node: " + selectedNode.nodeName + ", offset: " + selection.focusOffset;
else
info2.firstChild.data = "";
}, 500);
}
</script>
</head>
<body>
<h1>Standard Mode Page</h1>
<span>body font</span>
<table border="1">
<tr>
<td>Table font</td>
</tr>
</table>
<span>body font</span>
<pre id="info"> </pre>
<pre id="info2"> </pre>
<iframe id="contentFrame" style="width: 500px; height: 300px;" src="frame.html"></iframe>
</body>
</html>
frame.html (in compatibility mode):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "">
<html>
<head>
<title></title>
<style type="text/css">
body {
font-family: Arial;
font-size: 9pt;
font-style: italic;
font-weight: bold;
}
</style>
<script type="text/javascript">
window.onload = function () {
info.firstChild.data = "document.compatMode: " + document.compatMode;
editable.focus();
}
</script>
</head>
<body>
<h1>Compatibility Mode Frame</h1>
<span>body font</span>
<table border="1">
<tr>
<td>Table font</td>
</tr>
</table>
<span>body font</span>
<pre id="info"> </pre>
<div id="editable" contentEditable="true" style="border: 1px dotted red">
Editable
</div>
</body>
</html>
Note the difference in rendering the table, using the same CSS:
My question to experienced web developers: is this a supported scenario which can be used in production environment (IE8+ mostly, but occasionally Safari/Chrome/Firefox)? Is there a better way of doing this?
I've stumbled upon a related, albeit opposite question, which left me with mixed feelings.
[UPDATE] (based on the comments):
All JavaScript resides inside the main page and appears to work just fine. What's interesting (and great!), the inner frame's view is rendered in compatibility mode, yet standard mode features are available for its DOM (at least, when accessed from the main page). E.g. document.getSelection works (and does cross-browsers, too).
By supported scenario I mean any endorsement by W3C HTML and DOM standards. So far I haven't found a definitive answer to this. This behavior may as well be just a nice side effect, although the fact it works cross-browsers is promising.
MSDN says the following: As of IE9 mode, webpages cannot display multiple document modes. For example, consider a standards-based webpage that contains a frame element that displays content in quirks mode. IE9 mode displays the child frame in standards mode (because the parent document is in standards mode). According to my tests, this is not true; my sample works as desired in IE9: the main page is in standard mode, the frame page is in quirk mode. [EDITED] As pointed out in the comments, it is the Almost Standard Mode (i.e., not the classic quirk mode), with its own rendering rules.
As of IE9 mode, webpages cannot display multiple document modes. For example, consider a standards-based webpage that contains a frame
element that displays content in quirks mode. IE9 mode displays the
child frame in standards mode (because the parent document is in
standards mode).
According to my tests, this is not true; my sample
works as desired in IE9: the main page is in standard mode, the frame
page is in quirk mode.
Not quite; when your sample works as desired it's actually displayed in a single display mode, with quirks mode emulated for the frame content. You shouldn't care about the underlying mechanics as long as the resulting output matches what you were after, although there is some anecdotal evidence of differences between emulated and native modes (mostly to do with js DOM manipulation).
I'd be a bit more concerned about how IE10+ would handle such fringe scenarios:
Starting with IE11 Preview, document modes are deprecated and should
no longer be used, except on a temporary basis. Make sure to update
sites that rely on legacy features and document modes to reflect
modern standards.
Ninja edit: looks like this has already been resolved on SO; modifying the accepted solution to your needs you should omit Doctype and add <meta http-equiv="X-UA-Compatible" content="IE=5" />; X-UA-Compatibility correctly defined as per msdn spec
This is a pseudo-answer to your slightly non-specific question;
In regards to your apprehension to rely on this IE feature for "back-compatibility", I feel the same way. Microsoft has provided this option because there are lots of companies out there who take a long time to update their web content. This option is meant to allow them to have a quick and dirty stop-gap, not a permanent solution.
So, what's the permanent solution? If that is your question, then IMO this is the answer; don't rely on the stop-gap and develop the correct output for the reports.
Without knowing what those reports are it is impossible to properly advise you on that part, but here's a stab in the dark:
There are lots of options to convert "HTML" to PDF. (I put HTML in quotations because each rendering engine is bound to require different versions/standards of HTML and you'll need to know those assumptions before you pick one.) If you want output that will format 100% the same on any browser, then you want a format that is meant to be static and not change; like PDF. Plus, then you also have the printing options taken care of as well.

Can I not use embedded <style> CSS on Android?

I'm debugging a site on an Android HTC Sense. The site uses a lot of inserted content, which comes along with it's own CSS and JS like:
// wrapper id = snippet_id
<html>
<head>
<style type="text/css">
#snippet_id div {border: 1px solid red !important;}
div {border: 1px solid blue !important;}
</style>
</head>
<body>
<div>Hello World</div>
</body>
<html>
This is inserted into an existing page, so it sort these snippets are sort of like iFrames I guess.
Question:
Problem is, that while Javascript works fine, all CSS I'm specifying using <style> tags is being ignored. Any idea why?
EDIT:
Works on:
- Android 4.0.1
Does not work on:
- Android 2.3.1
- IOS 4.1
If I add the CSS to the main.css file being requested when the page loads, all is ok. If it's inside my gadget, it's not working.
EDIT:
So from what I can see, <style> does not seem to work on classes and id. If I use regular HTML elements as selectors it works.
EDIT:
My dev-site is here. I'm using a plugin called renderJs, which encapsultes HTML snippets (along with their CSS and JS) into resuable gadgets. Gadgets content will be appended to the page body, so although a gadget can act as a standalone HTML page, it can also be part of a page.
Example code from my page (I stripped out all gadgets but one below):
index.html - include index_wrapper gadget
<!DOCTYPE html>
<html itemscope itemtype="http://schema.org/Organization" lang="en" class="render">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../css/overrides.css">
<script data-main="../js/main.js" type="text/javascript" src="../js/libs/require/require.js"></script>
<title></title>
</head>
<body class="splash">
<div data-role="page" id="index">
<div id="index_wrapper" data-gadget="../gadgets/index_wrapper.html"></div>
</div>
</body>
</html>
The page has a gadget called index_wrapper link - code below:
<!DOCTYPE html>
<head></head>
<body>
<div id="index_social" data-gadget="../gadgets/social.html"></div>
<p class="mini t" data-i18n="gen.disclaimer"></p>
</body>
</html>
Which has another gadget called social here. This gadget includes some CSS, but on the devices in question, it is ignored (just saw, I'm missing a </div> in the index_wrapper, so trying to see if that fixed the problem, too).
The code below includes my fix:
<!DOCTYPE html>
<head>
<style type="text/css" scoped>
// will be ignroed
.el {width: 1px;}
.menu_social {text-align: center; margin: 1em 0;}
.action_menu {display: inline-block;}
.follow_us {display: inline-block; margin: 0; padding: 0 .5em 0 0;}
...
</head>
<body>
<div class="menu_social">
<div>
<span class="el ui-hidden-accessible"></span><!-- fallback for CSS not working -->
<div data-role="controlgroup" data-type="horizontal" data-theme="c" class="action_menu">
</div>
</div>
</div>
<script type="text/javascript">
//<![CDATA[
(function () {
$(document).ready(function() {
var gadget = RenderJs.getSelfGadget();
// fallback for old devices which cannot load <style> css
if (gadget.dom.find(".el").css('width') !== "1px") {
require(['text!../css/social.css'], function (t) {
var x = '<style>'+t+'</style>';
gadget.dom.append(x);
});
}
// trigger enhancement
$(this).trigger("render_enhance", {gadget: gadget.dom});
});
})();
//]]>
</script>
</body>
</html>
So aside from probably missing a closing </div> I'm still wondering why my embedded CSS is not working.
Looking at the generated HTML code (i.e., code as modified by JavaScript) of the demo page suggests that style elements are generated inside body. Although such elements are allowed by HTML5 drafts when the scoped attribute is present, support to that attribute seems to be nonexistent, and the style sheet is applied globally. It is possible however that some browsers do not apply it at all, at least when the style element is dynamically generated.
A better approach is to make all style sheets global to the document, preferably as external style sheets, and use contextual selectors to limit the rules to some elements only. And possibly using JavaScript to change classes of elements, rather than manipulating style sheets directly.
Ok. Ugly workaround:
In the inline section, set this:
<style>
.el {width: 1px;}
</style>
In the page, set hide an element el like this:
// ui-hidden-accessible is a JQM class, moving the item out of view
// since it uses pos:absolute, is needed to not break
// selects on the page (compare to JQM ui-icon)
<span class="el ui-hidden-accessible"> </span>
Then check for the width when running inline Javascript (which works) and require the inline CSS as a separate file, when the width is not at 1px
// fallback for old devices which cannot load <style> css
// gadget is my iframe-look-a-like
if (gadget.dom.find(".el").css('width') !== "1px") {
require(['text!../css/translate.css'], function (t) {
var x = '<style>'+t+'</style>';
gadget.dom.append(x);
});
}
Ugly and an extra HTTP request, but at least the CSS is working then.

VRML run a script

I am playing around with VRML at the moment, not through choice to be honest but for a project on Web 3D.
I am trying to make a touch sensor in VRML that will show and hide a Div in a webpage. I have tried writing a wee script using
browser.loadURL('javascript:someFunction()');
to try and test this.
The javascript is never called, however I know my touch sensor is ok as certain functions I have tried to use (e.g. if i spell 'browser' wrong) it throws up an error.
Perhaps this is just not supported by modern browsers?
Any assistance and advice would be greatly appreciated.
DEF alertScript Script {
eventIn SFTime make_alert
url [ "javascript:
function make_alert (value) {
Browser.loadURL('javascript:alert()');
}
" ]
}
ROUTE touchBack.touchTime TO alertScript.make_alert
Do they only want classic VRML or is X3D allowed ? (X3D is the name of the current version of VRML).
If you are allowed to use X3D (I don't see why not), you could use X3DOM which is a WebGL engine, you may even get extra points on your assignment :)
Here's an example that hides a div when you click on a 3D sphere:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Touchsensor in X3DOM</title>
<link href="x3dom.css" rel="stylesheet" />
<style>
#myDiv {
color: blue;
margin: 20px 0;
}
x3d {
display: block;
width: 600px;
height: 400px;
background: #EEEEEE;
border: none;
}
</style>
</head>
<body>
<div id="myDiv">
Click the sphere to hide this div
</div>
<x3d>
<Scene>
<Shape id="mySphere">
<Appearance>
<Material diffuseColor="0 1 0" />
</Appearance>
<Sphere/>
</Shape>
</Scene>
</x3d>
<script src="x3dom.js"></script>
<script>
(function() {
document.getElementById('mySphere').onclick = function(){
document.getElementById('myDiv').style.display = "none";
};
})();
</script>
</body>
</html>
And by the way, X3D is the recommended 3D technology by the HTML5 spec, it isn't dead at all :-)

Categories

Resources