IE11 bug - calling javascript getAttributeNode method brakes mergeAttributes - javascript

There is some really strange behavior in javasrcipt after recent update of IE (11.0.27) in IE=7 mode, in previous versions script below works as expected (including IE8-IE11.0.24) .
So it's caused by calling Element.getAttributeNode('class') , after this call is made on element that element will throw error (Unspecified Error) if you'll try to merge it`s attributes with another element with Element.mergeAttributes method.
Demo (happens only when devtools/console is turned off and in IE-7 mode with current IE11 version) : LINK
Question: Is there any way to avoid this, and is there any alternative methods for those mentioned above? Issue is that those two methods are heavily used by mootools and jquery selectors and my framework is based on mootools. So after I use selector which looks like $$('input[class=randomclass]') all inputs will be corupted and i`ll not be able to clone them (mergeAttributes).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<html>
<head>
<script type='text/javascript'>
window.onload = function() {
org = document.getElementById('o');
cln = document.getElementById('c');
btn1 = function() {
cln.mergeAttributes(org);
alert(cln.className)
}
btn2 = function() {
org.getAttributeNode('class');
try {
cln.mergeAttributes(org);
} catch (e) {
alert(e.description)
}
}
}
</script>
</head>
<body>
<div id='placeHolder'>
Original:
<input type='text' class='original' id='o'></input>
<br> Clone:
<input type='text' class='clone' id='c'></input>
<br>
</div>
<input type='button' value='mergeAttributes without "getAttributesNode" ' onclick='btn1()'>
<br>
<input type='button' value='mergeAttributes with "getAttributesNode" ' onclick='btn2()'>
<br>
</body>
</html>

It seems the issue is in the jQuery library. This solution was provided by cqrranthuohill3 from the dataTabes forum. He referenced Dottoro.com
In jquery.js in the cloneFixAttributes( src, dest ) function about line 6092. Replace:
// mergeAttributes, in contrast, only merges back on the
// original attributes, not the events
if ( dest.mergeAttributes ) {
dest.mergeAttributes( src );
}
With:
// mergeAttributes, in contrast, only merges back on the
// original attributes, not the events
try{
if ( dest.mergeAttributes ) {
dest.mergeAttributes( src );
}
} catch (exception) {
for (var i=0; i < src.attributes.length; i++) {
var attr = src.attributes[i];
var attrName = attr.name.toLowerCase ();
if (attrName != "id" && attrName != "name") {
dest.setAttribute (attr.name, attr.value);
}
}
}
Give that a go.

After some suggestion i manage to fix the problem related to Element.getAttributeNode('class') as it was broking Element.mergeAttributes(src), i had to replace all instances of Element.getAttributeNode in mootools with custom function.
Function which replaced default Element.getAttributeNode:
getAttributeNode_M = function(el, attr) {
var AllAttribues = el.attributes;
for (var i = 0; i < AllAttribues.length; i++) {
if (el.attributes[i].name.toLowerCase() == attr.toLowerCase()) {
return el.attributes[i];
}
}
return false;
}

Related

The value of input element changes but not shown in the browser(s)?

I wrote a live search field for a part of my form, when the suggestions come and user clicks on one of them, a js function (selectedService) is being called to get the innerHTML of the li which the user clicked on!
everything works perfectly when you look at the code in 'Inspect Element' of the browser, but not on the web page!
after the user clicks on the on the suggestion the value property of input element changes in the code but on the browser. the content of input field is still what the user is typing in it.
here's the code :
<!DOCTYPE html>
<html dir="rtl">
<head>
<meta charset="UTF-8">
</head>
<body>
<input value="" id="services" placeholder="click or type plz..."/>
<ul id="suggestions">
</ul>
<style>
/* some styles */
</style>
<script>
var input = document.getElementById("services");
var suggestions = document.getElementById("suggestions");
input.oninput = function() {
var q = input.value;
if (q.length < 2) {
suggestions.setAttribute("style","display: none");
return;
}
var xhr2 = new XMLHttpRequest;
xhr2.open("GET", "theURL/service-request-handler.php?q="+q, true);
xhr2.onreadystatechange = function() {
if (xhr2.readyState == 4 && xhr2.status == 200)
{
var result = xhr2.responseText;
console.log("server response = "+result);
var json = JSON.parse(result);
showSuggestions(json);
}
};
xhr2.send();
};
function showSuggestions(json) {
suggestions.setAttribute("style","display: block");
var li_list = '';
var i = 0;
for (i=0; i<json.length; i++)
li_list += '<li id="'+i+'" onclick="selectedService('+i+')">'+json[i]+'</li>';
suggestions.innerHTML = li_list;
}
function selectedService(i) {
li_target = document.getElementById(i);
console.log(li_target.innerHTML);
// input.innerHTML = li_target.innerHTML;
input.setAttribute("value",li_target.innerHTML);
suggestions.setAttribute("style","display: none");
}
</script>
</body>
</html>
the result in the Inspect Element :
I'd appreciate any help or suggestions :)
input.value = li_target.innerHTML
You can set value property directly:
input.value=li_target.innerHTML;
Probably you are using firefox browser, you should use this to work in both, chrome and firefox.
input.value = li_target.innerHTML;
This happens because property and attributes are different.
Attributes are defined on the HTML markup but properties are defined on the DOM.
You can use jQuery UI for autocomplete search.

Code works in Chrome and Firefox, but doesn't work in IE11

I have this small program that basically compares to sets of numbers and then will let me know if there are any matches and what those matches are. It works just fine in Chrome and Firefox, but when I try it in IE11, and hit the button, nothing appears and it doesn't seem to work. I have looked at other forums and topics but nothing I have tried seems to work. Any ideas?
Heres the code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
<HTML><HEAD><META content="IE=5.0000" http-equiv="X-UA-Compatible">
<META http-equiv="Content-Type" content="text/html; charset=unicode">
<SCRIPT>
function check() {
var a = document.getElementById("a").value.split("\n").filter(function(num) { return num.length > 0 });
var b = document.getElementById("b").value.split("\n").filter(function(num) { return num.length > 0 });
var results = "";
var numMatchesFound = 0;
for (x = 0; x < a.length; x++) {
for (y = 0; y < b.length; y++) {
if (a[x] == b[y]) {
numMatchesFound++;
results += "<br>" + b[y];
}
}
}
results = "<br>Found " + numMatchesFound + " matches." + results;
document.getElementById("result").innerHTML = results;
}
</SCRIPT>
<META name="GENERATOR" content="MSHTML 10.00.9200.16798"></HEAD>
<BODY>
<H1>Match finder</H1>
<P> Entries can be words,
numbers, or whatever.</P>
<H2>Paste a list of entries, one per line, in this
box:</H2><TEXTAREA id="a" rows="10" cols="30"></TEXTAREA> <BR>
<H2>Paste another list of entries, one per line, in this box:</H2><TEXTAREA id="b" rows="10" cols="30"></TEXTAREA>
<BR><BUTTON onclick="check()" type="button">Check for matches</BUTTON> <BR>
<DIV id="result"></DIV>
</BODY>
</HTML>
Take a look at the "Developer Tools", in the "Console" tab:
Object doesn't support property or method 'filter'
File: test.html, Line: 7, Column: 1
Despite the function reportedly being supported as of IE9 (http://www.w3schools.com/jsref/jsref_filter.asp), and Microsoft describing how to use it (https://msdn.microsoft.com/en-us/library/ff679973(v=vs.94).aspx), this is not available for some reason.
Thank goodness for jQuery = )
Or try modifying your meta tags. Pretty sure you told IE to pretend like it was IE5. I stripped your meta tags out and it worked just fine.

calling more than one function on the same button does not work for me (ajax)

i got a ajax procedure that is working ok, but now i need to add a new function to be called just once. so i add this to my current script to get the apex collection clean, but now nothing happens, i placed an alert to verify, but no alert is shown, i guess is because i am placing my clean script in wrong place or there must be something else missing.
// Clean Collection
function()
{
alert('Clean All');
var ajaxRequestd = new htmldb_Get(null,&APP_ID.,"APPLICATION_PROCESS=DEL_PRODUCTS",&APP_PAGE_ID.);
ajaxResult = ajaxRequestd.get();
}
here is my full script. thanks for your value tips !!
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Totals</title>
<script type="text/javascript">
$(function()
{
$("#Calculate").click
(
function()
{
// Clean Collection
function()
{
alert('Clean All');
var ajaxRequestd = new htmldb_Get(null,&APP_ID.,"APPLICATION_PROCESS=DEL_PRODUCTS",&APP_PAGE_ID.);
ajaxResult = ajaxRequestd.get();
}
$("input[name=f_qty]").each
(
function()
{
var valueInCurrentTextBox = $(this).val();
var productId = $(this).parents('tr').find("input[name=f_prod_id]").val();
$("#P12_PRODUCT_ID").val(productId);
if (valueInCurrentTextBox != '')
{
$("#P12_QTY").val(valueInCurrentTextBox);
var ajaxRequest = new htmldb_Get(null,&APP_ID.,"APPLICATION_PROCESS=ADD_PRODUCTS",&APP_PAGE_ID.);
ajaxRequest.add('P12_PRODUCT_ID',html_GetElement('P12_PRODUCT_ID').value);
ajaxRequest.add('P12_QTY',html_GetElement('P12_QTY').value);
ajaxResult = ajaxRequest.get();
}
}
);
alert('Updated!');
}
);
}
);
</script>
</head>
<body>
<div id="totals"></div>
<p align="center" style="clear: both;">
<button type="button" style="font-weight: bold;background-color:lightgray;margin-left:auto;margin-right:auto;display:block;margin-top:0%;margin-bottom:0%" id="Calculate">Add Products</button>
</p>
</body>
</html>
You're declaring that inner function, but never actually calling it. You could assign it to a variable and then call that, but it's actually not needed at all.
Try:
$(function()
{
$("#Calculate").click
(
function()
{
// Clean Collection
alert('Clean All');
var ajaxRequestd = new htmldb_Get(null,&APP_ID.,"APPLICATION_PROCESS=DEL_PRODUCTS",&APP_PAGE_ID.);
ajaxResult = ajaxRequestd.get();
$("input[name=f_qty]").each
(
function()
{
var valueInCurrentTextBox = $(this).val();
var productId = $(this).parents('tr').find("input[name=f_prod_id]").val();
$("#P12_PRODUCT_ID").val(productId);
if (valueInCurrentTextBox != '')
{
$("#P12_QTY").val(valueInCurrentTextBox);
var ajaxRequest = new htmldb_Get(null,&APP_ID.,"APPLICATION_PROCESS=ADD_PRODUCTS",&APP_PAGE_ID.);
ajaxRequest.add('P12_PRODUCT_ID',html_GetElement('P12_PRODUCT_ID').value);
ajaxRequest.add('P12_QTY',html_GetElement('P12_QTY').value);
ajaxResult = ajaxRequest.get();
}
}
);
alert('Updated!');
});
});

Javascript , is there a way to make the javascript disable all links except one

I want to redirect all links on one site to another domain. Except few menu links and one image in the site.. All I could find was this code, and it just disables all links
any ideas
function disable() {
links=document.getElementsByTagName('A');
for(var i=0; i<links.length; i++) {
links[i].href="javascript:return false";
}
}
window.onload=disable;
i want to show tons of demo templates that people can download , but those templates have all sorts of links that i dont want people to surf to , so i want to put one image inside the template saying Look at more templates. and thats the only link i want enabled
Using the script you have as an example just set a conditional. I used the inArray() function described here. The basic logic is to set an array called good_links that is a list of links you do not want neutralized. And then by using the inArray() function, the disable() function can now logically traverse all links but ignore the good_links:
<script type="text/javascript">
function disable(){
var good_links = new Array();
good_links[0] = "http://www.google.com/";
good_links[1] = "http://www.yahoo.com/";
good_links[2] = "http://www.bing.com/";
links=document.getElementsByTagName('A');
for(var i=0; i<links.length; i++) {
if (!inArray(links[i].href, good_links)) {
links[i].href="javascript:return false";
}
}
}
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
window.onload=disable;
</script>
Okay, here is my whole HTML file which works. The only links that should work are: Google, Yahoo & Bing. Apple, Catmoji & StackOverflow are disabled.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My Webpage</title>
<script type="text/javascript">
//<![CDATA[
function disable(){
var good_links = new Array();
good_links[0] = "http://www.google.com/";
good_links[1] = "http://www.yahoo.com/";
good_links[2] = "http://www.bing.com/";
links=document.getElementsByTagName('A');
for(var i=0; i<links.length; i++) {
if (!inArray(links[i].href, good_links)) {
links[i].href="javascript:return false";
}
}
}
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
window.onload=disable;
//]]>
</script>
</head>
<body>
http://www.google.com/<br />
http://www.apple.com/<br />
http://www.yahoo.com/<br />
http://www.catmoji.com/<br />
http://www.bing.com/<br />
http://www.stackoverflow.com/
</body>
</html>
You'll need to find some attribute of the links you do not want disabled, and then check for that while looping. For instance, if the image and menu links have # as their href attribute:
function disableLinks () {
var allLinks=document.getElementsByTagName('A');
for(var i=0; i<allLinks.length; i++) {
if (allLinks[i].href !== '#') {
allLinks[i].href="javascript:return false";
}
}
}
window.onload = disableLinks;
It may be worth mentioning that disabling/redirecting a bunch of links without a good reason is a great way to piss off your users and make them never return to your site.
If you're using Apache, and you can differentiate between links to redirect and those not to, you could adapt an Apache mod_rewrite rule...
Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*) http://www.domain.com/$1 [R=301,L]
The (.*) would have to change, but it's a start.

Smallest code possible to filter checkboxlist through javascript

Project doesn't need any javascript libraries such as jQuery, Dojo, Prototype so there is no easy way i suppose. I would like to have in-depth answers for the question explaining how would one do this. As most of you might know asp.net checkboxlist emits a markup like below in Flow repeatLayout.
<span>
<checkbox><label></br>
<checkbox><label></br>
<checkbox><label></br>
</span>
i haven't put the ending/closing tags for simplicity. We have a textbox for searching through this list of checkbox.Now comes the question,
How would i Filter the checkboxlist when user types the search term in the textbox and hide the unmatched checkbox+label.
some more questions i would like getting answers for that are related to above
Is there any ready made STANDALONE script for this purpose?
Is there a pattern , article, post explaining the glitches, points to remember while providing search functionality? something like onkeydown don't do this,
My Idea right now would be have a cached collection of label tags innerHTML then loop through each tag and check for search term, when found hide all others but show only matching.[My Concern is what will happen when list is too long, on every keypress looping is not the best idea i suppose]
Your suggestions, answers, solution, scripts are welcome
This solution is based on Ktash's answer. I made it cause I want to learn more about javascript, DOM navigating and RegExp.
I changed "keypress" event with "keydown" since the previous doesn't trigger on backspace/delete so deleting all the characters with backspace/delete still left the list filtered.
[Default.aspx]
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="RealtimeCheckBoxListFiltering.Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
window.onload = function () {
var tmr = false;
var labels = document.getElementById('cblItem').getElementsByTagName('label');
var func = function () {
if (tmr)
clearTimeout(tmr);
tmr = setTimeout(function () {
var regx = new RegExp(document.getElementById('inputSearch').value);
for (var i = 0, size = labels.length; i < size; i++)
if (document.getElementById('inputSearch').value.length > 0) {
if (labels[i].textContent.match(regx)) setItemVisibility(i, true);
else setItemVisibility(i, false);
}
else
setItemVisibility(i, true);
}, 500);
function setItemVisibility(position, visible)
{
if (visible)
{
labels[position].style.display = '';
labels[position].previousSibling.style.display = '';
if (labels[position].nextSibling != null)
labels[position].nextSibling.style.display = '';
}
else
{
labels[position].style.display = 'none';
labels[position].previousSibling.style.display = 'none';
if (labels[position].nextSibling != null)
labels[position].nextSibling.style.display = 'none';
}
}
}
if (document.attachEvent) document.getElementById('inputSearch').attachEvent('onkeypress', func); // IE compatibility
else document.getElementById('inputSearch').addEventListener('keydown', func, false); // other browsers
};
</script>
</head>
<body>
<form id="form1" runat="server">
<table>
<tr>
<td>
<asp:TextBox runat="server" ID="inputSearch" ClientIDMode="Static" />
</td>
</tr>
<tr>
<td>
<asp:CheckBoxList runat="server" ID="cblItem" ClientIDMode="Static" RepeatLayout="Flow" />
</td>
</tr>
</table>
</form>
</body>
</html>
[Default.aspx.cs]
using System;
using System.Collections.Generic;
namespace RealtimeCheckBoxListFiltering
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
cblItem.DataSource = new List<string>() { "qwe", "asd", "zxc", "qaz", "wsx", "edc", "qsc", "esz" };
cblItem.DataBind();
}
}
}
var tmr = false;
var labels = document.getElementsByTagName('label')
var func = function() {
if (tmr) clearTimeout(tmr);
tmr = setTimeout(function () {
var regx = new Regex(inputVal); /* Input value here */
for(var i = 0, size = labels.length; i < size; i++) {
if(regx.match(labels[i].textContent || labels[i].innerText)) labels[i].style.display = 'block';
else labels[i].style.display = 'none';
}
}, 100);
}
if (document.attachEvent) inputField.attachEvent('onkeypress', func);
else inputField.addEventListener('keypress', func, false);
Not perfect, and not all the way complete, but it should get you started on it. There is a 100 millisecond delay before it performs the loop so that it won't run on every keypress, but likely just after they've stopped typing. Probably want to play with the value a bit as you see fit, but it gives you the general idea. Also, I didn't set the variables for inputField nor inputVal, but those I assume you would already know how to grab. If your labels are not a static list onload, you'll probably want to get the list every time.

Categories

Resources