Cufon issue in Safari Reader - safari

It turns out that Safari Reader handles Cufon in an interesting way. When Safari Reader handles "Cufonized" text it leaves the canvas elements thereby creating gaps in the output.
Upon further investigation and attempting to solve the issue I found that there is seemingly no way to control the output of safari reader from the developer side without effecting the whole site.
Does anyone have any suggestions?

Yeah, So that is an issue cufon has when it comes to using safari "reader", or as most people would know it, the "reader" button that shows up on the ipad/iphone/ipod broswer.
for example, let's say we have a cufonized h1 tag like so:
<h1>Hello World!</h1>.
well this is what cufon does to it, minus all those attributes and inline styling:
<h1>
<cufon>
<canvas></canvas>
<cufontext>Hello</cufontext>
</cufon>
<cufon>
<canvas></canvas>
<cufontext>World!</cufontext>
</cufon>
</h1>
And when the "reader" opens it it reads something like this:
_ Hello _ World!.
where the "_" is a blank space caused by the element.
__ So __ Imagine __ Reading __ Text __ Like __ This!!!
annoying!!
So I modified the cufon-yui.js file Version 1.09i so the output would be something like this,
<h1>
<beforetext>Hello World!</text>
<cufon>
<canvas></canvas>
</cufon>
<cufon>
<canvas></canvas>
</cufon>
</h1>
So when "reader" opens it, it looks like so:
Hello World! _ _
Where the blank canvases come after the text, so you dont get that weird effect.
So here is the fix:
On line 1240 - 1259 (might be different for some, but easy to spot), I changed the following
styleSheet.appendChild(document.createTextNode((
'cufon{text-indent:0;}' +
'#media screen,projection{' +
'cufon{display:inline;display:inline-block;position:relative;vertical-align:middle;' +
(HAS_BROKEN_LINEHEIGHT
? ''
: 'font-size:1px;line-height:1px;') +
'}cufon cufontext{display:-moz-inline-box;display:inline-block;width:0;height:0;text-align:left;text-indent:-10000in;}' +
'beforetext{display:-moz-inline-box;display:inline-block;width:0;height:0;text-align:left;text-indent:-10000in;position:absolute;left:-99999px}' +
(HAS_INLINE_BLOCK
? 'cufon canvas{position:relative;}'
: 'cufon canvas{position:absolute;}') +
'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy{display:none;}' +
'cufonglue{white-space:nowrap;display:inline-block;}' +
'.cufon-viewport-resizing cufonglue{white-space:normal;}' +
'}' +
'#media print{' +
'cufon{padding:0; display:none;}' + // Firefox 2
'cufon canvas{display:none;}' +
'beforetext {text-indent:0;text-align:left;display:block; width:100%; height:auto}'+
'}'
).replace(/;/g, '!important;')));
This will style the new "beforetext" element and the for print and screen,
On line 1296 right after "return function(font, text, style, options, node, el)" I added :
var tagtype = $(el).get(0).tagName;
if (tagtype == "BEFORETEXT"){return null;}
This is to avoid rewdoing the beforetext to itself on hover options.
Now from line 1336 - 1353 (again might be different, but easy to spot) I changed it to
if (redraw) {
wrapper = node;
canvas = node.firstChild;
if (options.printable) {
$(el).find('beforetext').append(document.createTextNode(text));
}
}
else {
wrapper = document.createElement('cufon');
canvas = document.createElement('canvas');
wrapper.className = 'cufon cufon-canvas';
wrapper.setAttribute('alt', text);
wrapper.appendChild(canvas);
if (options.printable) {
var beforeText = document.createElement('beforetext');
$(el).not(':has(beforetext)').prepend('<beforetext></beforetext>');
$(el).find('beforetext').append(document.createTextNode(text));
}
}
The above adds the "beforetext" element only once, and then appends the text to that element as it creates each cufon text, and also reapplies it on hover options so it doesn't get errased.
And that's it. Hope this helps someone out-there. And feel free to correct me, imporve it, or find a better solution, I'd like to know
of alternative better ways. Happy coding all.
P.S
Sorry for the long response. Just trying to make sure someone with the same issue understands whats going on.

Related

How to set height of WebView according to the length of content in Nativescript-Vue?

Update: I used HtmlView and yes, the height is dynamic with the content,
but it seems like not support <img />
I'm currently using WebView to render the markdown content as below
<WebView :src="marked_content" height="1200px" margin="20dp" />
The result is fixed at 1200px with scrollBar as expected, but what I actually want to do is to render the whole markdown content with various height and without scrollBar.
Anyone may help, please?
PS: Any other methods which may render markdown content is welcome! Thank you!
Do you have control over the website, if Yes you can do this
https://discourse.nativescript.org/t/dynamic-webview-height/4215/2?u=manojdcoder
I have worked out how to do this without plugins.
There is a solution above which appends the URL with a hash containing the page height. It didn't work for me because I'm adding HTML code directly.
For example
src="<p>blah blah</p>"
This is a plain JS solution, so you'll have to rework it to get it working in Vue / Typescript.
Give your WebView an id, do not set the height, and add the "loaded" and "loadFinished" handlers.
For the loaded handler.
platformModule = require("tns-core-modules/platform");
var webViewSrcObj = {};
exports.webViewLoaded = function(webargs){
if(platformModule.isAndroid){console.log("IS ANDROID!!!"); return false;}
webview = webargs.object;
if(webview.height == "auto"){
webViewSrcObj[webview.id] = webview.src;
webview.src += '<script>function getPageHeight(){if(document.documentElement.clientHeight>document.body.clientHeight){height = document.documentElement.clientHeight}else{height = document.body.clientHeight}; ph = document.getElementById("pageHeight"); window.location = "pageHeight.html?height="+height;} setTimeout(getPageHeight, 1);</script>';
}
}
It checks the platform, and returns false if it is Android (Android works fine already).
Then it checks if the height is set to "auto" (which is default).
if it is set to auto, it will copy the HTML content. I'll explain more about this later. It then appends the html with some JavaScript code that calculates the view height, and then redirects to an empty page. It does this in order to use the query string for the page height. Make sure that page exists in your app folder to avoid any page not found errors!
Then for the onLoadeFinished handler...
exports.webViewLoadFinished = function(webargs){
if(platformModule.isAndroid){
console.log("IS ANDROID!!!"); return false;
}
webview = webargs.object;
if(webargs.url.indexOf("?height") > -1){
height = (webargs.url).split("?height=");
height = height[1].substr(0, height[1].length)/1;
webview.height = height; webview.src = webViewSrcObj[webview.id];
}
}
This will check to see if the query string height value exists.
If so it uses the height value to set the height of the webview.
And finally it adds the HTML content that was copied in the onLoaded handler.
My initial testing works well even with multiple webviews in a page.
I haven’t done extensive testing, but it might help to increase the setTimeout time if you experience any problems.
If anyone is able to improve this solution, please share your results.

jQuery innerHTML cannot set property

I have a <div id="tguide"> that I use as a place holder. I was told iframes are inferior to jquery load. So this is what I have:`$(window).on('load resize',function(e){
var transferguidelocation = "../"
var title = $(document).attr('title');
if(title == 'System Manuals') {
var transferguidelocation = "../SystemManuals/"
};
document.getElementById("tguide").innerHTML='<object type="text/html" data="' + transferguidelocation + 'shared/TransferGuide.html" style="width:100%;height:100%;"></object>';
As you can first it checks to see which page it's on, then it adds an extra folder location to the TransferGuide.html location.
The file loads into the <div> no problem, it looks exactly the way I want it to and data is correct, the problem is that I'm getting the below error in the browser inspector:
It's a bit annoying and I'm not a fan of the errors. Does anyone know how I can get rid of this?
I figured it out. I was referencing my custom.js file before the js.min file, so it didn't recognize it. I just reversed the two and the error went away

Strange offset with Watir/Capybara and PhantomJS

I want to detect the location of elements on a page using Watir and PhantomJS.
My second approach using Capybara resulted in the same offset.
While the elements on the left side look good, the right side is misaligned:
I made the screenshot before and after I grab the positions for each element with element.wd.location, but the offset is always the same. I used evaluate_script and .getBoundingClientRect() with Capybara.
One thing looks suspicious to me: The search input field is not loaded correctly and not only shows a misalignment, but also a different size and the magnifying glass isn't shown. I don't know if this causes the offset.
I tested it with pure PhantomJS 2.1.1 (phantomjs file.js):
var fs = require('fs');
var page = require('webpage').create();
page.viewportSize = {
width: 1024,
height: 768
};
page.open('http://en.wikipedia.org/', function() {
var positions = page.evaluate(function() {
positions = [];
elements = document.getElementsByTagName('IMG');
for (var i=0, l=elements.length; i<l; i++) {
pos = elements[i].getBoundingClientRect();
positions.push(pos.left + ' ' + pos.top);
};
return positions;
});
fs.write('test.txt', positions.join("\r\n"), 'w');
page.render('test.png');
phantom.exit();
});
Same result: If you open the test.png, you see the an image on the right (left: 952px, top: 259px), but the test.txt shows it shifted to the left (left: 891px).
Do you know what could cause this problem?
Do you know what could cause this offset?
A bug in PhantomJS v2.1.1 or in the embedded Qt WebEngine.
Is there any workaround ?
No.
But I want it to work anyway, how?
Fix it yourself or hire someone to fix it or wait for it to be fixed.
Note that the issue no longer occurs in version 2.5, but it is still in beta :
https://github.com/ariya/phantomjs/milestone/16
https://bitbucket.org/ariya/phantomjs/downloads/
Here's a screenshot taken with phantomjs-2.5.0-beta :
This seems to be an issue in PhantomJS.
On the GitHub thread of the issue, #dantarion seems to have found a solution:
I am running this as well.
My fix is to run the following on the page in an evaluate block to force PhantomJS to render at the right height viewport. It works for my use case, and while I want to see it fixed in 2.2, since its still an issue I thought I'd post here.
document.getElementsByTagName("body")[0].style.overflow = "hidden";
document.getElementsByTagName("body")[0].style.height = "1080px";
document.getElementsByTagName("body")[0].style.maxHeight = "1080px";
document.getElementsByTagName("html")[0].style.overflow = "hidden";
document.getElementsByTagName("html")[0].style.height = "1080px";
document.getElementsByTagName("html")[0].style.maxHeight = "1080px";
It seems to be solving the problem. The only problem being that background-size: cover might still be off (as reported by #Luke-SF).

Selenium 2: How to save a HTML page including all referenced resources (css, js, images...)?

In Selenium 2, the WebDriver object only offers a method getPageSource() which saves the raw HTML page without any CSS, JS, images etc.
Is there a way to also save all referenced resources in the HTML page (similar to HtmlUnit's HtmlPage.save())?
I know I'm royally late with my answer, but I didn't really find an answer for this question when I was searching myself. So I did something myself, hope I can help some people still.
For c# here's how I did it:
using system.net;
string DataDirectory = "C:\\Temp\\AutoTest\\Data\\";
string PageSourceHTML = Driver.PageSource;
string[] StringSeparators = new string[] { "<" };
string[] Result = PageSourceHTML.Split(StringSeparators, StringSplitOptions.None);
string CSSFile;
string FileName = "filename.html";
System.IO.File.WriteAllText(DataDirectory + FileName, PageSourceHTML);
foreach(string S in Result)
{
if(S.Contains("stylesheet"))
{
CSSFile = S.Substring(28); // strip off "link rel="stylesheet" href="
CSSFile = CSSFile.Substring(0,CSSFile.Length-10); // strip off characters behind, like " />" and newline, spaces until next "<" was found. Can and probably will be different in your case.
System.IO.Directory.CreateDirectory(DataDirectory + "\\" + CSSFile.Substring(0, CSSFile.LastIndexOf("/"))); //create the CSS direcotry structure
var Client = new WebClient();
Client.DownloadFile(Browser.Browser.WebUrl + "/" + CSSFile, DataDirectory + "\\" + CSSFile); // download the file and save it with the same filename under the same relative path.
}
}
I'm sure it could be improved to include any unforeseen situations, but for my website in test it will always work like this.
Nope. If you can, go for HtmlUnit for this particular task.
The best you could do, I think, is Robot. Press Ctrl + S simultaneously, the confirm with Enter. It's blind, it's imperfect, but it's the closest thing to your need.
You can use the selenium interactions to handle it.
using OpenQA.Selenium.Interactions;
There are a few ways to do it as well. One of the ways that I handle something like this, is to find an item central to the page, or whichever area that you wish to save, and do an actions builder.
var htmlElement = driver.FindElement(By.XPath("//your path"));
Actions action = new Actions(driver);
try
{
action.MoveToElement(htmlElement).ContextClick(htmlElement).SendKeys("p").Build().Perform();
}
catch(WebDriverException){}
This will simply right click on the area, and then send the key "p" which is the 'Save Page As' hotkey in firefox when right clicking. Another way is to have the builder send the keys.
var htmlElement = driver.FindElement(By.Xpath("//your path"));
action.MoveToElement(htmlElement);
try
{
action.KeyDown(Keys.Control).SendKeys("S").KeyUp(Keys.Control).Build().Perform();
}
catch(WebDriverException){}
Note that in both cases, if you leave the scope of the driver, say a windows form, then you will have to switch your case / code to handle the windows form when it pops up. Selenium will also have issues with nothing being returned after the keys are sent, so the Try Catches are there for that. If anyone has a way to work around that, it would be awesome.

Dynamic Height Adjusting w/ Open Social Gadget

I have a gadget that is a glossary with a number of different pages. users can upload new words to the data source and those words will be pulled into the glossary through an AJAX call.
I want to resize the gadget window everytime the window is re-sized OR a new letter is selected and the page height changes (ie the gadget html block height).
Google developers has posted this on their website. However, this clearly is not working for me. The scrolling is not registering on the iframe and the height is not adjusting when the window is resized.
Here are my ModulePrefs
title="Climate Policy and Science Glossary"
description="Paragraph format"
height="300"
scrolling="true">
<Require feature="dynamic-height"/>
<Require feature="opensocial-0.8" />
Here is the gadget's script telling it to adjust:
window.onresize = adjust;
function adjust() {
var wndwH = gadgets.window.getViewportDimensions().height,
wgtH = $('#_glossary').closest('html').height,
h = Math.min(wndwH, wgtH);
gadgets.window.adjustHeight(h);
}
gadgets.util.registerOnLoadHandler(adjust);
What's going on? Am I doing something wrong or is there anyone else out there having trouble with Google's dynamic height??
The adjust function really only needs:
function adjust() {
gadgets.window.adjustHeight();
}
That should fit everything automatically.