I am creating a style element and I need to put some CSS into it. The below code works in Chrome, Safari and FF, but fails in IE8:
var styleElement = document.createElement("style");
styleElement.type = "text/css";
styleElement.innerHTML = "body{background:red}";
document.head.appendChild(styleElement);
In IE8, the code fails when it comes to the innerHTML part. I've tried doing:
var inner = document.createTextNode("body{background:red}");
styleElement.appendChild(inner);
But this also fails with "Unexpected call to method or property access."
I'm looking for a workaround or fix.
Use .styleSheet.cssText
NOTE: this seems to be REALLY slow in IE8 compared to modifying individual elements style.
Is there a faster way to modify style sheets dynamically in IE?
This is slow in IE8:
styleElement.styleSheet.cssText = "body{background:red}";
This is also slow in IE8 (assumes the style object to be modified is the 1st style element in the head):
document.styleSheets[0].cssText = "body{background:red}";
This is fast in IE8:
document.body.style.background = "red";
Try to use styleElement.innerText
Related
Currently I am scraping article news sites, in the process of getting its main content, I ran into the issue that a lot of them have embedded tweets in them like these:
I use XPath expressions with XPath helper(chrome addon) in order to test if I can get content, then add this expression to scrapy python, but with elements that are inside a #shadow-root elements seem to be outside the scope of the DOM, I am looking for a way to get content inside these types of elements, preferably with XPath.
Most web scrapers, including Scrapy, don't support the Shadow DOM, so you will not be able to access elements in shadow trees at all.
And even if a web scraper did support the Shadow DOM, XPath is not supported at all. Only selectors are supported to some extent, as documented in the CSS Scoping spec.
One way to scrape pages containing shadow DOMs with tools that don't work with shadow DOM API is to recursively iterate over shadow DOM elements and replace them with their HTML code:
// Returns HTML of given shadow DOM.
const getShadowDomHtml = (shadowRoot) => {
let shadowHTML = '';
for (let el of shadowRoot.childNodes) {
shadowHTML += el.nodeValue || el.outerHTML;
}
return shadowHTML;
};
// Recursively replaces shadow DOMs with their HTML.
const replaceShadowDomsWithHtml = (rootElement) => {
for (let el of rootElement.querySelectorAll('*')) {
if (el.shadowRoot) {
replaceShadowDomsWithHtml(el.shadowRoot)
el.innerHTML += getShadowDomHtml(el.shadowRoot);
}
}
};
replaceShadowDomsWithHtml(document.body);
If you are scraping using a full browser (Chrome with Puppeteer, PhantomJS, etc.) then just inject this script to the page. Important is to execute this after the whole page is rendered because it possibly breaks the JS code of shadow DOM components.
Check full article I wrote on this topic: https://kb.apify.com/tips-and-tricks/how-to-scrape-pages-with-shadow-dom
I am using the below code for fetching the font size of a "link" on IE.
Browser("BB").Page("PP").Link("link").Object.CurrentStyle.fontSize
However, if I use the same code on FireFox, QTP/UFT throws error:
object required "Object.CurrentStyle".
After alot of research and exploration I found that for FireFox it is not Object.CurrentStyle, but it is Object.Style which is an inbuilt function in QTP, and used below code
Browser("BB").Page("PP").Link("link").Object.style.fontSize
but I'm not fetching the results for the firefox
I had similar issues when switching between browsers. IE has a special style object that is not supported in other browsers. I suggest a more generic tactic, treat style for what it is - an html attribute. You could go pure DOM, but lets use the UFT test objects:
Step 1: find the html node you want to extract style from:
Set element = Browser("creationtime:=0").Page("title:=HelloWorld").WebElement("xpath:=//html/body/div[#id='something']")
Step 2: extract the style data
attributeValue = element.Object.GetAttribute("style")
attributeValue is now a string containing the style attribute data, it can be split, RegExp'd or what ever you need
`TestObject.Object.currentStyle.fontSize`
will work only on IE not on FireFox, we may get the option to use "Style" in place of "currentStyle" for FireFox but that doesn't work properly. Also the FontSize is read as "FontSize" in IE and "font-size" in Firefox
To retrieve the required information form the application on Firefox
set FXObj= Browser("title:=Test_2").Page("title:=Test_2").Link("text:=link")
Set webElem = FXObj.Object
Set compStyle=Browser("title:=Test_2").Page("title:=Test_2").Object.defaultView.getComputedStyle(webElem, "")
fntsize = CompStyle.getPropertyValue("font-size")
Print fntsize
The FireFox DOM does not support all of the same methods as IE. I've solved similar problems of cross-platform testing by getting the "application version" property of the browser and using a function to determine the values I'm looking for based on the browser type.
It's not glamorous but it's saved a lot of heads for my team.
You can find the FireFox page/document DOM here.
We are using java ajaxtags as a library to populate auto complete values for textbox. It is working perfectly in most of the browsers (Firefox, ie6, ie7 etc...).
But in case of IE8 the position of auto complete results are not linked with the actual textbox, instead it is shifted towards down. It is happening only in IE8.
Please suggest a solution to resolve this issue and to be able to the display auto complete results in a proper way.
Thanks for your help in advance.
Found the solution myself...
In control.js file I have added the following condition to get it worked
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
// Adding the following condtion will fix the issue with IE8
if(navigator.appVersion.indexOf('MSIE')>0) {
update.style.display = 'inline';
}
Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
}
I've developed a Firefox extension for displaying explanations for some unusual words. My problem is that my tooltip get's modified by other stylesheets of the current page. So on some pages my stylesheet looks fine and on some it's totally messed up. Is there a way to limit my stylesheet to my tooltip notes so that stylesheets from the webpage wouldn't affect mine?
I'm loading my stylesheet that way:
initTooltipStyle: function(on) {
var sss = Cc["#mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
var uri = makeURI("resource://tooltip/tooltip.css");
if (sss.sheetRegistered(uri, sss.USER_SHEET))
sss.unregisterSheet(uri, sss.USER_SHEET);
if (on)
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
},
I have experienced this problem. Most of the time the style property which you didn't applied to your element will be easily overriden by webpages. For instance, if you didn't declare margin for your div element and webpage has declared div{margin:0;} your element will also inherit it. Try adding reset.css to your elemets(http://meyerweb.com/eric/tools/css/reset/).
Then try adding your elements into the root elemnt of the page instead of body. document.documentElement.appendChild(). These techniques helped me.
Hope that helps!
I have an Ajax request that returns search results, and I am dynamically creating DOM elements to display those results. This is working as expected in all the browsers I've tested except for IE8.
The request is returning fine, the JavaScript is running successfully, and the elements are being created, but the elements are not being displayed in the page. They only appear after a mouse-click somewhere on the page.
I ran a quick test that ran the callback code without the Ajax request, and it behaved as expected there. So I'm wondering if this has something to do with the way IE8 is managing the callback thread. Has anyone else seen behavior like this, or have insight on it?
The callback is fundamentally very simple. I have reproduced with this:
function catchResults(response) {
var contentBlock = document.getElementById('divResults');
var divResults = document.createElement('div');
var txt = document.createTextNode("Results");
divResults.appendChild(txt);
contentBlock.appendChild(divResults);
}
I am using JQuery.ajax to make the call.
I have seen the proper behavior in FireFox and Chrome.
Thanks for the help!
I ran into this problem not so long ago on IE8.
I think this might be a problem with IE8 not re-rendering the elements in question.
An easy way to confirm this is to add a class to the parent element and then remove it. This should trigger IE8 to re-render the element.
If contentBlock is the parent element then you could test with the following:
Javascript version:
// Variable storing the test class name
var testClass = "testClass";
// Add test class to element
contentBlock.className += " "+testClass;
// Remove test class from element
var reg = new RegExp('(\\s|^)'+testClass+'(\\s|$)');
contentBlock.className=contentBlock.className.replace(reg,' ');
jQuery version:
// Variable storing the test class name
var testClass = "testClass";
// Add test class to element and then remove it
$('#divResults').addClass(testClass).removeClass(testClass);
Just put it at end of the function after you appendChild. Hopefully this should fix your issue.
Reference: http://www.openjs.com/scripts/dom/class_manipulation.php