IE refuse to change array elements into text - javascript

I have problem with my javascript code working on IE. I think I know exactly why it is working wrong, although I dont know how to change it.
Let me explain:
My code consist of small part of code inside $(document).ready() and a lot of inside $ajax.success(). The first part works normally, then I thought I have problem with ajax - that it simply dont work on IE. The error was:
Script65535 unexpected call to method or property access.
Jquery - 1.7.2.min.js line 5847, character 5
And line 5847 is APPEND function!!! It simply must work!
5844 append: function() {
5845 return this.domManip(arguments, true, function( elem ) {
5846 if ( this.nodeType === 1 ) {
5847 this.appendChild( elem );
5848 }
5849 });
5850 }
Then I found on google, that IE have problems when the multi-dimension array is changed to text. And only two appends in my ajax.success() function appends the content of arrays!
$('.display_info_here').append(tab_szablony[i][lang_number-2].toUpperCase()+'</br></br>');
I tried to change the array to text in another way, but it didnt worked
var arrr = tab_szablony[i][lang_number-2];
$('.display_info_here').append(arrr.toUpperCase()+'</br></br>');
It works on IE 9+, but not in 8 :(
Thanks for any help :)

Related

Array.from() with HTMLcollection does not seem to work in Chrome browser

I have a JavaScript piece of code that works on all browsers (even IE) but fail with Chrome on my HUAWEI P8 Lite with Android 6.
Chrome is version 71.0.3578.99.
The faulty code is var class_arr = Array.from(class); where class is a HTMLcollection.
It seems like Array.from() is failing although it should be supported by Chrome on mobile.
Also, I've noticed that this same code used to work one update ago, and not two updates ago strangely.
You can test the problem with this URL (of course this won't be valid as long as if I'll find a solution to my problem). You need to open the sidebar on the left and try to zoom in the map with the Plus or Minus button.
EDIT
Here is the code where I use Array.from():
export function updateSlider(all_sliders, ol_layers, class_layers) {
// updates slider with the actual opacity of the layers
for (var i = 0, len_i = all_sliders.length; i < len_i; ++i) {
var curr_slider = all_sliders[i];
// get layer from ol_layers whose title is equal to current slider id
// Find the value of the first element/object in the array, otherwise undefined is returned
// (https://stackoverflow.com/a/13964186/1979665)
var lyr = ol_layers.find(obj => {
return obj.values_["title"] === curr_slider.getAttribute("id")
});
// get class_layer (layerswitcher) from class_layers whose title is equal to current slider id
// (first we need to convert class_layers from HTMLCollection to array otherwise .find will fail)
var class_layers_arr = Array.from(class_layers);
var class_elem = class_layers_arr.find(obj => {
return obj.innerText.replace('\t','') === curr_slider.getAttribute("id")
});
// get current layer opacity and set it as the value of current slider
var curr_opacity = lyr.values_["opacity"];
curr_slider.setAttribute("value", curr_opacity);
// create new li element
var li_elem = document.createElement("LI");
// add slider input to li elem
li_elem.appendChild(curr_slider);
// add li with layer legend after layer li
insertAfter(li_elem, class_elem);
changeOpacity(curr_slider, ol_layers);
}
}
class_layers is first defined in another script as var class_layers = document.getElementsByClassName("layer");
EDIT 2
Ok, so apparently the problem is related to Chrome in general, not only on mobile. In fact, if you try the above URL in Chrome Desktop, you can reproduce the error by opening the sidebar (on the left), then closing it and pressing the + or - symbol to zoom in the map. I guess it has to do with the way click events are treated by either my code and OpenLayers. I am probably deleting this question as it sounds like I need to dig further in problematic.
SOLUTION
Not deleting because I think it maybe useful for others to see the solution.
Here is the link to the OpenLayers github issue I created and closed: https://github.com/openlayers/openlayers/issues/9105.
The problem was the event "change:resolution" fired by the View class of OL (v5.3.0) that is emitted multiple times during animation (problem also quoted here).
NEW CONSIDERATION
Turns out that I still had the problem on mobile devices.
The real fix was not to use innerText in my code and switch to innerHTML, as it was always empty in (and only in) Chrome, while with the other browsers it was not (I could actually see the string). If you are interested I can try to provide an example, but unfortunately I could not find much on this problem in the web...
It's not Array.from() problem.
Check your class_elem variable
It's undefined (because no element found for your conditions) and then it fails when your trying to get parentNode of undefined in:
export function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

For loop index undefined in IE9 for initial pass

On this page: http://koncordia.marketingassociates.com/19892arc/
I have a slideshow that I created custom prev/next links for. Each selection you make on the page advances it one slide forward. The progress bar at the top allows you to click a previous slide, and jump more than one back if you want (you can go from step 4 or step 1 for example).
This multi-step jump works fine in all the current major browsers, but the client uses IE9, and this is where I do not understand the source of the issue.
The following are the relevant methods in this issue. To mimic a user jumping back one or more slides I have a for loop iterate over simulatePrevClick() as many times as necessary; it's not sexy but it works.
The issue arises on the initial pass in IE9. The console spits out "undefined" for the first pass, but it says 0 for all other browsers (including IE 10 and 11) which is correct. If I remove the method call within the loop the iteration works perfectly, so it has something to do with the .click() event or way the method is called, but I don't know what.
No matter what, IE9 will show the immediate previous slide no matter how many they click back; the progress bar be out of sync if they click back more than one in this instance. The undefined result is not showing as an error, either.
//Highlight the right number of progress buttons
highlightProgressBar: function( slideNumber ) {
$(".btn-progress").attr('disabled', 'disabled').removeClass('active'); //Disabled all
$("#progress-wrapper a:lt(" + slideNumber + ")").removeAttr('disabled'); //Disable select number
$("#progress-wrapper a:eq(" + (slideNumber - 1) + ")").addClass('active'); //Add active to the specified button clicked
},
simulateNextClick: function () {
//The value of this must match what the responsiveslides function creates for the prev/next buttons (seen when you inspect element)
$(".transparent-btns_nav.transparent-btns1_nav.next").click();
},
simulatePrevClick: function () {
//The value of this must match what the responsiveslides function creates for the prev/next buttons (seen when you inspect element)
$(".transparent-btns_nav.transparent-btns1_nav.prev").click();
},
toggleProgressBar: function( clickedSlideNumber, activeSlideNumber ) {
var numSlides = activeSlideNumber - clickedSlideNumber;
for (var i=0; i < numSlides; i++) { //Anticipate user may click more than one step back
this.simulatePrevClick();
console.log(i); // **shows "undefined" on first pass in IE9 only**
}
this.highlightProgressBar(clickedSlideNumber);
}
Try to move the var i = 0 declaration out of the loop.
var i = 0;
for (; i < numSlides; i++) {}
It's really strange that that should happen.
This is just a guess, but I looked through the rest of your source code, and its possible that the root of your problem could be due to whenever you actually implement your toggleProgressBar function, in this area:
$(".btn-progress").click(function() {
var currentSlideID = $("#progress-wrapper").find('a.active').attr('id').split("-");
var clickedSlideID = $(this).attr('id').split("-");
slideFn.toggleProgressBar( clickedSlideID[1], currentSlideID[1] );
});
If I see right, your toggleProgressBar wants to accepts two numbers. However, what you're passing in are string literals:
slideFn.toggleProgressBar( "2", "1" );
ID attributes are output as strings, not numbers. I just tested the following in Chrome, and it worked:
"2" - "1" === 1 //true
This is because I guess V8 (Chrome's JS engine) coerces the two string literals into numbers. However, (while I have not tested it), this tells me that it's possible that IE might not be coercing the two strings into numbers (like I said, I don't know this for a fact, but this is something you might try debugging). Try this and see if it has any effect:
//first option
slideFn.toggleProgressBar( +clickedSlideID[1], +currentSlideID[1] );
//the + sign will typecast your strings into numbers
//second option
slideFn.toggleProgressBar( parseInt(clickedSlideID[1]), parseInt(currentSlideID[1]) );
However, in my experience, parseInt runs a little bit slower than using + to typecast the strings into numbers.
IE uses the Chakra JS engine, which I believe follows the standards of ECMAScript 3, which is from 1999. I haven't read through the standard, but it's worth considering the possibility that it has something to do with the issue.
Edit
Here's your problem:
$("#progress-wrapper").find('a.active') ==> []
The first time, there are no a.active elements. Thus, whenever you try to call split on an empty array, it throws a TypeError.
You need to give your first .btn-progress the class active, because the first time around, your first .btn-progress looks like this:
1
There's no active class. Only subsequent .btn-progress elements receive the class active whenever you click the .btn-continue. Your first one never does. Therefore, clickedSlideID[1] and currentSlideID[1] are undefined the first go around. It probably breaks in IE9 because IE9 doesn't understand i < undefined, but it's possible that other more modern browsers go ahead and execute anyway.
Somewhere in the beginning of your code, then, you need to do something like this:
$('.btn-progress').eq(0).addClass('active');
I just tried this in the console on your page, and it worked just fine. After I added the class active to the fist .btn-progress, currentSlideID[1] was now 1, and not undefined.

jQuery that works in Firefox but not in IE

Ok guys/girls.
Below is some jQuery that runs in Firefox but no IE. I have no idea why it craps out in one and not the other.
Anyone??
function SwapTextAssetforPOS() {
$("*").each(function () {
if ($(this).children().length == 0) {
$(this).text($(this).text().replace('Assets', 'POS'));
$(this).text($(this).text().replace('Asset', 'POS'));
$(this).text($(this).text().replace('assets', 'POS'));
$(this).text($(this).text().replace('asset', 'POS'));
}
});
}
Sorry folks - the error that I get is:-
SCRIPT65535: Unexpected call to method or property access.
jquery-1.6.min.js, line 16 character 60352
EDIT:------------------------------------------------------------------------------------
Ok so an update - I removed the * selector and IE no longer blows up, my issue now is that I cant figure how to get it to do the replace on the element. I have the following code to ping up all the text elements in the object:
function SwapTextAssetforPOS() {
var containerElementByID = $("#assetDetailContents");
containerElementByID.children().children().each(function () {
var $this = $(this);
alert($this.text());
});
This chucks me up an alert for every bit of text, however some is contained within a table, some is within a span, and some is just there. I have no control over a majority of this stuff so my new question is how do I get the previous replace to work using this type of selector. -- I can believe how painful this is..
Cheers again
I see the problem in my IE browser. When you do the $("*").each... it takes every single element in the page (including title, script, etc). When you do .text(), looks like it fails for some elements in IE for which .text() doesn't make sense. Replace "*" for "div" and it should work for the divs for example.Maybe you could do something like if ($(this).text()) {$(this).text($(this).text().replace('Assets', 'POS'));} to make sure the text() is defined for that element.
Still, going through the whole DOM is overkill. Can you add a class to the elements that can have the text?, like class="replaceable" so you could just do a $(".replaceable").text(...
Ok folks - so firstly thanks for the help.
I have resolved the issue by cobbling a number of suggestions together and by doing a little bit of investigative work.
In a nutshell IE was crapping out when it ran up against an tag. I no not why but this is where it fell over every time.
function SwapTextAssetforPOS() {
var overlaycon = $("#jq-selectionHelper").find("*:not(img)"); //This line simply looks at the div surrounding the template and returns (to an array I believe) every element therein except for img tag
//as this breaks in IE when tying to do the replace text stuff below.
overlaycon.each(function () {
var $this = $(this);
if ($this.children().length == 0) {
$this.text($(this).text().replace('Assets', 'POS'));
$this.text($(this).text().replace('Asset', 'POS'));
$this.text($(this).text().replace('assets', 'POS'));
$this.text($(this).text().replace('asset', 'POS'));
}
});
}
This code runs and I believe is a lot more efficient than my original offering. Any further suggestions for performance re-factoring are welcome but thank the lord this is now working.
Thanks again for all the help.
Regards
This code has no problem as seen here . I tested in IE and FF both works fine
http://jsfiddle.net/wKWRC/
You should use F12 developer tool for IE and see what error you are getting that way others can know what exact problem is . You can debug script and see where you are getting error . IE is sensitive to javascript errors and its possible there is some error before you are calling this function .
http://msdn.microsoft.com/en-us/library/gg699336%28v=vs.85%29.aspx
Just a hunch but you might be running out of memory in IE.
First, using $('*') is never advisable, its better that you narrow it down with a selector like $('p').
Also, every time you call $(this) you create a new jQuery object, so if there are a lot of elements on your page you're making 9 objects every time.
The convention is to set $this = $(this) at the begining of the function so you only use one object.
function SwapTextAssetforPOS() {
$("*").each(function () {
var $this = $(this);
if ($this.children().length == 0) {
$this.text($this.text().replace('Assets', 'POS'));
$this.text($this.text().replace('Asset', 'POS'));
$this.text($this.text().replace('assets', 'POS'));
$this.text($this.text().replace('asset', 'POS'));
}
});
}
try it like this
for (var i = 0, replacements = ['Assets','assets','asset','Asset']; i < 4; i++)
$("*:contains('" + replacements[i] +"')").map(function() { this.innerHTML = this.innerHTML.replace(/asset(s){0,1}/igm, 'POS'); })

Javascript/jQuery function yields undefined in <IE8

A short while back I asked a question here about how I could calculate when a heading was longer than one line within a given container, and subsequently wrap each of these lines in a <span>:
Use Javascript/jQuery to determine where a heading breaks to the next line?
I chose an answer which worked great for me, at least until I checked in IE7 and IE6, in which all the headings handled by this script rendered as
"undefinedundefinedundefinedundefinedundefinedundefined[...]"
on the page. As I'm not really a JavaScript person (that's why I asked such a question in the first place), it's really tough for me to figure out where the problem is. I assumed an undefined variable or something, but I just can't seem to grasp it.
Can anyone help?
I'll repeat the code here, but please refer to the link above for context:
$(function(){
$h = $('.fixed').find('h3');
$h.each(function(i,e){
var txt = $(e).text();
$th = $('<h3 />').prependTo($(e).parent());
var lh = $(e).text('X').height();
$(e).text('');
while (txt.length > 0) {
$th.text($th.text() + txt[0]);
txt = txt.slice(1);
if (($th.height() > lh) || (txt.length <= 0)) {
var shc = $th.text().split(' ');
var ph = shc.slice(0,-1).join(' ')+' ';
if (txt.length <= 0) { ph += shc.pop(); }
$('<span />').text(ph).appendTo($(e));
$th.text(shc.pop());
}
}
$th.remove();
})
});
You need to change
$th.text($th.text() + txt[0]);
to be
$th.text($th.text() + txt.charAt(0));
IE<8 doesn't accept string positions through array indexes ;)
The styling doesn't work, but that'll be a CSS issue which I couldn't fix before leaving. But everything is wrapped in spans :)
Nothing jumps out at me. But, since you mentioned in your comment to your question that you see "undefined" in Firebug, I would start there. Even though those browsers are failing gracefully, the fact that you see undefined there is your first hint to finding the problem for the harder-to-diagnose IE6/7. I would use Firebug and either breakpoint in the function, or use some console.log() calls to document what the values that you are working with are each step of the way. Once you start seeing undefined... you have likely found your problem.

why if (element.innerHTML == "") is not working in firefox

why is if (element.innerHTML == "") not working in firefox
but works fine in IE , any ideas please ?
Hard to say without seeing your HTML, but I'd say probably because you have some empty white space in the element, and IE doesn't treat that as a text node, while FF does.
I believe it is actually a more strict standards compliance to treat any empty white space between tags as a text node, but IE doesn't comply.
You could do:
var htmlstring = element.innerHTML;
// use the native .trim() if it exists
// otherwise use a regular expression
htmlstring = (htmlstring.trim) ? htmlstring.trim() : htmlstring.replace(/^\s+/,'');
if(htmlstring == '') {...
Or just get rid of the whitespace in your HTML markup manually.
An alternative method to check for the empty string is to check the length:
element.innerHTML.length == 0
But, you'd still have to trim() if you had a whitespace string you wanted to match.
You could check if element.innerHTML.trim() == "" for the best results. However, then you have to extend the string prototype with a trim() method:
if (!String.prototype.trim) {
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };
}
if (element.innerHTML.trim() == "") {
//do something
}
For me, it seemed like setting my innerHTML was not working in Firefox nor Chrome but it did work in IE because of my error. It turned out that I was never getting the element using getElementById in the first place. IE seems to do just fine with elements which are defined with name= with getElementById but Firefox and Chrome was more stringent and accepts only id= elements. (More correctly in my view)
I hope this saves somebody some frustration.
Why does IE do these sorts of things and confuse people...

Categories

Resources