IE 10 + jQuery - Not able to use "append" function - javascript

I am running an HTML 5 application using the KendoUI framework. Once of the screens deal with XML data that needs to be parsed and processed.
This screen needs to be shown as a popup and that data is shown in a grid inside this popup. To do this, I am calling a function on clicking the "show-popup" button inside which I have the following piece of code :
var tTranslationXML = XMLFromString(_SelectedCategoryValueRecord.DisplayTextTranslation);
.
.
.
// other stuff but nothing that changes "tTranslationXML"
.
.
if (_SelectedCategoryValueRecord.DisplayTextTranslation) // and there are values in the translation field
{
var $language = $(tTranslationXML).find('Language');
var $oldTranslation = $($language).find("en-US");
if ($oldTranslation.length == 0)
$oldTranslation = $($language).find(GetCorrectedCase("en-US"));
if ($oldTranslation.length == 0) {
var $newTranslation = $.createElementNS("en-US").text(_UpdatedDisplayText);
$language.append($newTranslation);
}
}
And if you are wondering what "XMLFromString" is, its nothing but a simple helper to parse the XML data from a string variable
function XMLFromString(pXMLString)
{
if (!pXMLString)
pXMLString = "<Language></Language>";
if (window.ActiveXObject) {
var oXML = new ActiveXObject("Microsoft.XMLDOM");
oXML.loadXML(pXMLString);
return oXML;
} else {
return (new DOMParser()).parseFromString(pXMLString, "text/xml");
}
}
My issue is that this works fine on Chrome and Firefox but I get an error in IE10 when this particular line executes -
"$language.append($newTranslation);"
I am basically trying to append a new translation value to the contents of my variable here.
The error is as follows :
SCRIPT13: Type mismatch
jquery-1.8.3.min.js, line 2 character 71981
Any ideas on how to solve this?

Sorry for the delayed response.
I figured out that the issue was to avoid using the method "createElementNS" and instead use the "createElement" method when creating the parent node. Subsequent appendages to this node do not throw up any issues. However there will issues when you append to a node that was originally created using "createElementNS".
This seems specific to IE10 because the NS method worked fine on chrome, FF and Safari.
Thank you all for the tips and ideas.

Related

Cannot get ExecuteScriptAsync() to work as expected

I'm trying to set a HTML input to read-only using ExecuteScriptAsync. I can make it work, but it's not an ideal scenario, so I'm wondering if anyone knows why it doesn't work the way I would expect it to.
I'm using Cef3, version 63.
I tried to see if it's a timing issue and doesn't appear to be.
I tried invalidating the view of the browser but that doesn't seem to help.
The code I currently have, which works:
public void SetReadOnly()
{
var script = #"
(function(){
var labelTags = document.getElementsByTagName('label');
var searchingText = 'Notification Initiator';
var found;
for (var i=0; i<labelTags.length; i++)
{
if(labelTags[i].textContent == searchingText)
{
found = labelTags[i]
break;
}
}
if(found)
{
found.innerHTML='Notification Initiator (Automatic)';
var input;
input = found.nextElementSibling;
if(input)
{
input.setAttribute('readonly', 'readonly');
}
}})()
";
_viewer.Browser.ExecuteScriptAsync(script);
_viewer.Browser.ExecuteScriptAsync(script);
}
now, if I remove
found.innerHTML='Notification Initiator (Automatic)';
the input is no longer shown as read-only. The HTML source of the loaded webpage does show it as read-only, but it seems like the frame doesn't get re-rendered once that property is set.
Another issue is that I'm executing the script twice. If I run it only once I don't get the desired result. I'm thinking this could be a problem with V8 Context that is required for the script to run. Apparently running the script will create the context, so that could be the reason why running it twice works.
I have been trying to figure this out for hours, haven't found anything that would explain this weird behaviour. Does anyone have a clue?
Thanks!

How to completely download page source, instead of partial download?

I'm scraping dynamic data from a website. For some reason the PageSource that I get() is partial. However, it is not partial when I view the page source directly from Chrome or Firefox browsers. I would like to know an answer that will enable me to completely scrape the data from the page.
For my application, I want to scrape programmatically using a .Net web browser or similar. I've tried using Selenium WebDriver 2.48.2 with ChromeDriver; I've also tried PhantomJSDriver; I've also tried WebClient; and also HttpWebRequest. All with .Net 4.6.1.
The url: http://contests.covers.com/KingOfCovers/Contestant/PendingPicks/ARTDB
None of the following are working...
Attempt #1: HttpWebRequest
var urlContent = "";
try
{
var request = (HttpWebRequest) WebRequest.Create(url);
request.CookieContainer = new CookieContainer();
if (cookies != null)
{
foreach (Cookie cookie in cookies)
{
request.CookieContainer.Add(cookie);
}
}
var responseTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse,request.EndGetResponse,null);
using (var response = (HttpWebResponse)await responseTask)
{
if (response.Cookies != null)
{
foreach (Cookie cookie in response.Cookies)
{
cookies.Add(cookie);
}
}
using (var sr = new StreamReader(response.GetResponseStream()))
{
urlContent = sr.ReadToEnd();
}
}
Attempt #2: WebClient
// requires async method signature
using (WebClient client = new WebClient())
{
var task = await client.DownloadStringTaskAsync(url);
return task;
}
Attempt #3: PhantomJSDriver
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
using (var driver = new PhantomJSDriver(driverService))
{
driver.Navigate().GoToUrl(url);
WaitForAjax(driver);
string source = driver.PageSource;
return source;
}
public static void WaitForAjax(PhantomJSDriver driver)
{
while (true) // Handle timeout somewhere
{
var ajaxIsComplete = (bool)(driver as IJavaScriptExecutor).ExecuteScript("return jQuery.active == 0");
if (ajaxIsComplete)
break;
Thread.Sleep(100);
}
}
I also tried ChromeDriver using page object model. That code is too long to paste here; nonetheless: it has the exact same result as the other 3 attempts.
Expected Results
The data table from the url is complete, without any missing data. For example, here is a screenshot to compare to the screen shot below. The thing to observe is that there is NOT an "...". Instead there is the data. This can reproduced by opening the url in Firefox or Chrome, right click, and View Page Source.
Actual Results
Observe that where the "..." is a big gap, as the arrow indicates in the screen shot. There should be many rows of content in place of that "...". This can be reproduced using any of the above attempts above.
Please note that the url is dynamic data. You will likely not see the exact same results as the screen shots. Nonetheless, the exercise can be repeated it will simply look different than the screen shots. A quick test to understand that there is missing data is to compare the Page Source line count: the "complete" data set will have nearly twice as many rows in the html.
Ok, as requested. glad to have helped. :)
But in your C# were are you copying from?, in your code you have -> urlContent = sr.ReadToEnd(); How are you seeing, copying the result from this?. Are you copying from the debugger?, if so it's maybe the object inspector of the debugger that's trimming. Have you tried getting the result from urlContent and saving to file?. eg. System.IO.File.WriteAllText(#"temp.txt",urlContent);

Error handling "Out of Memory Exception" in browser?

I am debugging a javascript/html5 web app that uses a lot of memory. Occasionally I get an error message in the console window saying
"uncaught exception: out of memory".
Is there a way for me to gracefully handle this error inside the app?
Ultimately I need to re-write parts of this to prevent this from happening in the first place.
You should calclulate size of your localStorage,
window.localStorage is full
as a solution is to try to add something
var localStorageSpace = function(){
var allStrings = '';
for(var key in window.localStorage){
if(window.localStorage.hasOwnProperty(key)){
allStrings += window.localStorage[key];
}
}
return allStrings ? 3 + ((allStrings.length*16)/(8*1024)) + ' KB' : 'Empty (0 KB)';
};
var storageIsFull = function () {
var size = localStorageSpace(); // old size
// try to add data
var er;
try {
window.localStorage.setItem("test-size", "1");
} catch(er) {}
// check if data added
var isFull = (size === localStorageSpace());
window.localStorage.removeItem("test-size");
return isFull;
}
I also got the same error message recently when working on a project having lots of JS and sending Json, but the solution which I found was to update input type="submit" attribute to input type="button". I know there are limitations of using input type="button"..> and the solution looks weird, but if your application has ajax with JS,Json data, you can give it a try. Thanks.
Faced the same problem in Firefox then later I came to know I was trying to reload a HTML page even before setting up some data into local-storage inside if loop. So you need to take care of that one and also check somewhere ID is repeating or not.
But same thing was working great in Chrome. Maybe Chrome is more Intelligent.

IE9 sees XML nodes at different indexes than other browsers

Here is a snippet from my attempt at cross-browser functionality:
xmlhttp.open("GET", "/wp-content/testimonials.xml", true);
if (xmlhttp.addEventListener) {
xmlhttp.addEventListener("load", retrieveTestimonial, false);
}
else if (xmlhttp.attachEvent) {
xmlhttp.attachEvent("onload", retrieveTestimonial);
}
xmlhttp.send();
function retrieveTestimonial () {
xmlDoc = xmlhttp.responseXML;
//Get DOM elements ready to be replaced by relevant testimonial info
var testimonial = document.getElementById("foot-testimonial");
var xmlTags = xmlDoc.getElementsByTagName("PROGRAM");
... more
The reason I included this particular block of code is because my script renders just fine in Chrome, Firefox, IE11, Safari, and even the stock Android browser. However, in IE9 I'm getting undefined for some variables that are set in the retrieveTestimonial function. If I try to log any of those variables (xmlTags, etc.) out to the console in IE9 I get 'is undefined'. So, from what I can tell, the function is not being called which suggests to me that the XHR load event is not firing.
EDIT: The function is firing, as I am able to log the variable xmlDoc to the console (object). For some reason, IE9 does not like some of my XML assignments because they are returning undefined. Here is the rest of the function:
for(var i = 0; i < xmlTags.length; i++) {
//If the program name from the URL matches the <WEBTITLE> value
if (progName == xmlTags[i].childNodes[1].childNodes[0].nodeValue) {
// Get each relevant piece of info from the XML file
var progTitle = xmlTags[i].childNodes[3].childNodes[0].nodeValue;
var studentName = xmlTags[i].childNodes[5].childNodes[0].nodeValue;
var textBody = xmlTags[i].childNodes[7].childNodes[0].nodeValue;
break;
}
IE9 does not seem to like seeing nodes at the same index as other browsers, though I haven't a clue as to why.
Is there a known workaround for this or am I just missing something simple? I'd hate to rewrite the script in jQuery, for instance, considering it's working like a charm everywhere else.

How do I get HTML Markup for createRange() in Firefox

I am currently using code similar to this:
try {
// IE ONLY
var theElement = "myElementName";
window.frames[theElement].focus();
var selection = window.frames[theElement].document.selection.createRange();
alert ( selection.htmlText );
} catch(e) {
var selection = window.frames[theElement].document.getSelection();
alert ( selection );
}
As you can see, I am accessing a node from an iframe (no fun already). I am definitely in new territory here, so am sure there are more issues to arise, but right now, I am trying to get Firefox to give me the same result as IE.
In IE, I can access the HTML code of the selection by using the (apparently IE-only) htmlText property of the object returned by createRange(). What I am looking for is the Firefox equivalent to that (or a function that I can use to give me the same result).
Anyone know how to do this?
This works in Firefox 2 and later (untested in earlier versions):
var selection = window.frames[theElement].getSelection();
var range = selection.getRangeAt(0);
var div = document.createElement("div");
div.appendChild(range.cloneContents());
alert(div.innerHTML);

Categories

Resources