I'm trying to find the cause of an unwanted value modification so I can remove the bug. When I turn off javascript for my page it includes this element after loading:
<input type="hidden" value="5123" name="report[sub_district_id]" id="report_sub_district_id">
but when I have javascript on, the same element looks like this after page load:
<input type="hidden" value="" name="report[sub_district_id]" id="report_sub_district_id">
I can't work out what code is unsetting the value property.
I've got one method that I know of that modifies the value. I've tried putting an alert in that method, but it's not triggered. I've also tried commenting out that method, but still the change happens. Perhaps some of my other JS accidentally hooks onto this element, but it seems unlikely. Perhaps the change is caused by some code in my framework (Rails with Materialize).
I've also tried adding DOM breakpoints "attribute modified" and "subtree modified" on this element, and "subtree modified" on the parent element, but none of these breakpoints are triggered.
The "attribute modified" breakpoint does trigger when my code modifies the value of the input at some point after the page is loaded, but I'm trying to find what is happening when "page:change" event is triggered, and this breakpoint is not triggering - perhaps because the DOM is not loaded yet.
I've tried the answers to this question but they don't help because they don't show how to make a breakpoint on an element change event that triggers before the DOM is loaded.
I'm using Chromium browser 48.0.2564.116 on Ubuntu 15.10 (64-bit)
How can I find what the cause of this bug is?
Debug after insert this code on top line of your page.
setInterval(function() {
var value = $("#report_sub_district_id").val();
if(value !== 5123) debugger;
},10);
and,
Maybe any Chrome extension program might cause the problem.
You should disable your all Chrome extensions.
TL;DR is there's no easy way.
So working backwards from the code that was actually changing, I don't think there is a way with browser's debugging tools to put a breakpoint here. However with an educated guess about the dom node's property that was getting changed, you could (assuming you run soon enough in the page) set a breakpoint that would help you out.
You found that the code in question was $('#parent-div-id input').val('').
Now .val() in jQuery just finds the actual node element and sets node.value = "blah"; The important distinction here is that it was changing a "property" on the node, and not an "attribute". You'll notice that all the DOMAttribute etc breakpoints talk about node attributes. If you take a node and edit the html's attribute, by say doing $('#parent-div-id input').attr('value', 'blah'), the breakpoint would get hit. The list of properties on a node is much larger than the list of HTML attributes, and the debugging tools only put breakpoints on HTML attribute modifications.
However in this case, you know the element in question (the input element), and the property that was getting messed with (the value property), so you could have done what was suggested in this answer, and redefined the property.
Example code here:
var node = $('#parent-div-id input')[0];
Object.defineProperty(node, 'value', {
get: function () {
return node._value;
},
set: function (value) {
debugger; // sets breakpoint
node._value = value;
}
});
All you'd need to do is get that code to run early enough in the page. To do that I'd probably set a breakpoint on the first line of the first javascript file loaded in the network tab.
Related
I am using jQuery to append elements to a div, and all works fine.
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
However, I'd like the div to appear by fading in, instead of abruptly.
I notice though that I get an error when I try to access graphic properties on my dynamically generated element. So this, for example fails:
new_div.hide().fadeIn();
The console reports the following error:
TypeError: jQuery.curCSS is not a function
Do I understand this correctly, that this fails because current css properties are not defined for the dynamically generated element? Or what else can be goingg wrong?
Important edit
Additional checking and working on this pointed out to a complete misunderstanding from my part. This has nothing to do with the fact that the element was dynamically generated. I got the same thing by calling fadeIn() on whatever element.
I sincerely apologize!
I still didn't get, though, why this happens
Adding elements to the DOM takes some time, miliseconds maybe, but it's still a reason for jquery not be able to find the element.
This process might be even slower if the DOM is a large html page.
Write your code like this:
var new_div = $('<div>My stuff</div>');
new_div.appendTo("#container");
setTimeout( function(){
new_div.hide().fadeIn();
} , 150); // 100 could be also good
It might be enough time for jquery to catch the element.
I would add an id to keep track of all elements I'm creating (just my preference, but it makes it easier to code it).
var new_div = '<div id="myNewDiv1" style="display:none;">My Styff</div>'
$('body').append(new_div);
$('#myNewDiv1').fadeIn();
It does seem to be a compatibility question, although I wasn't able to figure out exactly why and how to fix it.
Adding this code fixes the problem though:
jQuery.curCSS = function(element, prop, val) {
return jQuery(element).css(prop, val);
};
Update 3 - 10/09/2013: Just tested this with Version 29.0.1547.66 m and the problem still persists. If anyone else can test this out and let me know the results that would be great. You need an inline element such as a span with some text in, have it relatively positioned and moved by however many pixels you want from left and top. Then set up some jScript to change the current inner html of the element to something else and you should see it remain the same in the viewport but change correctly in the DOM.
Update 2: After a bit more testing the problem seems to occur on elements that are inline such as span, or have CSS that makes them inline, but that are also relatively positioned, it seems to be this combination that is causing the issue. After posting the bug on Chromium it has been flagged as a cr-Blink-Rendering issue which looks to be the engine that renders the DOM in the broswer viewport. I am using Version 29.0.1547.57 (the current version ends .66 but mine has not updated due to an error). So if you're on the latest version this issue may no longer be there.
Update: On further investigation I think the problem is with the latest Chrome build Version 29.0.1547.57 m As I tested the element in an inline fashion in IE9 and Firefox 21 and it worked fine. I have filed a bug report for this on chromium
I'm having a problem (that I have not been able to recreate with jsfiddle) where I perform an ajax request, obtain some values and place them within span elements that exist within my page.
I have a very odd problem where the ajax request is working and bringing the values back. The values are being inserted into the span elements via jQuerys .html' method and when I check the DOM using Chrome developer tools I can see the new value in the span.
However, what I see on the page doesn't reflect this, it still shows the old value. Yet if I attempt to highlight the value, it instantly changes to the correct value (the value that is showing in the DOM).
I have even tried to update the spans value before the ajax call (as the value I am using is being obtained from jQuery UI's slider widget) but this still yields the same results.
Has anyone else come across this?
EDIT: Here is some of the code
HTML
<div id="NewLoanSliderAmount" class="NewLoanSliderRules"></div>
<span id="NewLoanSliderAmountDisplay" class="NewLoanDisplay">£600</span>
The slider code. This is the version where I attempt to update it directly from the slider value
$("#NewLoanSliderAmount").slider({
value: amount,
min: 300,
max: amount,
step: 100,
change: function (event, ui) {
$("#NewLoanSliderAmountDisplay").html("£" + ui.value);
window.CkSpace.GetLoanValues();
}
});
Here is the ajax code:
(function (CkSpace, $, undefined) {
CkSpace.GetLoanValues = function () {
var url = "/Home/UpdateAPR";
$.get(url, { Amount: $("#NewLoanSliderAmount").slider("value"), Length: $("#NewLoanSliderLength").slider("value") }, function (data) {
$("#NewLoanAmount").html("£"+data.LoanAdvance);
$("#NewLoanLength").html(data.LoanTerm);
$("#NewLoanMonthlyCost").html("£"+data.LoanInstalment);
$("#NewLoanTotal").html(data.LoanGrossRepyable);
$("#NewLoanAPR").html(data.LoanAPR+"%");
$("#NewLoanSliderAmountDisplay").html("£" + data.LoanAdvance);
});
}
} (window.CkSpace = window.CkSpace || {}, jQuery));
EDIT 2:
Another thing to note is that if i set a break point on the span being populated and step through it, it updates perfectly every time in Chrome developer tools
I've figured out what was causing the problem although I don't know WHY it is causing the problem.
First off I tried changing the span to a div and adding display:inline to the css. It still didn't work.
I then removed the inline display and all of a sudden, as a block level element it works.
If anyone knows more about why this is and can elaborate then please do!
EDIT: On further investigation I think the problem is with the latest Chrome build Version 29.0.1547.57 m As I tested the element in an inline fashion in IE9 and Firefox 21 and it worked fine. I think it's time to file a bug report!
I have some crazy app done almost 100% by manipulating the DOM and I find myself in the unfortunate position of changing something in it. As there are probably around 100 different scripts that do God knows what, I have no clue in which file should I look to make my changes. So, I want to ask, is there a way (using Firebug maybe or something similar) to know where a specific piece of html was generated? I'm a C developer, so I'm not very good at this, it drives me crazy.
Are all the elements added at the page load, or partially in the response to the user input? (clicking etc.)
for stuff added with the response to your actions, you can use Firebug's "Break On Next" button in the "Script" tab. To active BON you have to click it, or, in just-shipped Firebug 1.10.0a8, use keyboard shortcut ALT-CTRL-B (useful when you have event listeners bound to mouse movements). Then, when any piece of JS is going to be executed in reaction to your click etc., you will hit a breakpoint.
for stuff added at page load time, you may use the trick of extending the native functions (this might sound crazy - yeah it is, don't do it in production!) like appendChild, insertBefore, replaceChild. Just insert the appropriate code at the very top of your main HTML file, so all the code below will "see" the change.
Unfortunately, this does not work in Firefox due to a bug. But works in Opera and I guess in Chrome as well.
When you extend the native function, you can inject any code before really adding the node to the page. For instance, call console.log or create a breakpoint, to inspect the current page state. You can try playing with breakpoints to see the available variables properties inside those function to adjust what you push to console.log.
For this code:
<!doctype html>
<html>
<head>
<script type="text/javascript">
// this should work in Firefox but it does not -- https://bugzilla.mozilla.org/show_bug.cgi?id=618379
// works at least in Opera, probably Chrome too
Node.prototype._appendChild = Node.prototype.appendChild;
Node.prototype.appendChild = function(child) {
console.log("appending " + child + " to " + this);
return this._appendChild(child); // call the original function with the original parameters
}
// this works in Firefox
document._createElement = document.createElement;
document.createElement = function(tagName){
console.log("creating " + tagName);
return this._createElement(tagName);
}
</script>
</head>
<body>
<script type="text/javascript">
var p = document.createElement("p");
p.appendChild( document.createTextNode("abc"));
document.body.appendChild(p);
</script>
</body>
</html>
Opera outputs:
creating p appendChild.html:14
appending [object Text] to [object HTMLParagraphElement] appendChild.html:7
appending [object HTMLParagraphElement] to [object HTMLBodyElement] appendChild.html:7
To overcome the weakness of Firefox (that you can't override appendChild), you may use the trick: place the code below instead in the top of your HTML
<script>
Node.prototype._appendChild = function(child) {
console.log("appending " + child + " to " + this);
return this.appendChild(child)
};
</script>
and then, use Fiddler proxy by creating auto-responders (WMV tutorial, 9.9 MB) where you manually replace all calls to .appendChild with ._appendChild (you can use Notepad++ for "find replace in all opened files"). Creating auto-responders and hand-tampering requests can be mundane, but it's extremely powerful. To quickly create auto-responder rule, load the page when Fiddler is active, then drag'n'drop files as in the picture below. For each file, right click and choose "Generate File" from menu (this will put a file on the desktop) or create a file by yourself in different location. (it's good to open Fiddler-generated files and remove response headers from them; BTW "Generate file" puts real contents only if the response header was 200, so make sure to load the page with CTRL-F5 to skip the cache).
In Chrome you can inspect an element and right click on it. This menu gives you some options to break when something below the element is changed or when it's own attributes change. Maybe one of those breakpoints will find what you are looking for?
Assuming you've got access to the raw (hopefully un-minified/obfuscated) JS files, maybe just search them for text strings related to DOM manipulation and/or attributes of the node you're trying to find the creation of? I'd try things like "appendChild" "createElement" and the node's ID/class names.
You could also set break points all over the script files, and step through them as the page loads to help you narrow down where to look. Might help to start by just "pausing" the JS execution and stepping through from the very beginning.
If you can share the code (a link to the live site would do fine) I'd be happy to take a look.
If you are using the jQuery framework in your javascript to make the DOM changes then you may find the fireQuery plugin for FireBug in the firefox browser may get you the information you need.
Example:
It adds additional information to the standard HTML view by superimposing additional jquery element information to the display to provide a deeper insight into how your javascript is amending the page content.
I hope that helps you out.
I'm working on some custom Javascript for a CMS template at work. I want to be able to make a certain <li> element on the page receive the class of "current" for that page only. So in the global page head I have something like this:
<script type="text/javascript">
function makeCurrent(id) {
var current = document.getElementById(id);
current.setAttribute("class", "current"); // for most browsers
current.setAttribute("className", "current"); // for ie
}
</script>
Then in each individual page <head>, I have something like this:
<script type="text/javascript">makeCurrent("undergraduate")</script>
On the page I have a nav <ul>, with something like:
<li id="undergraduate">Undergraduate Program</li>
<li id="graduate">Graduate Program</li>
etc.
When I load the page, the class is not applied. When I look in the Firebug console, it gives the error message:
current is null
(x) current.setAttribute("class", "current");
I'm still getting the hang of writing solid, raw javascript (learning backwards after jQuery, you know how it goes), but I want to write it in just JS. What idiotic newbie mistake am I making?
Thanks everyone!
If you execute the javascript before the DOM tree has finished loading, it will return null. So an idea would be to call the function all the way at the end before you close the body tag.
This is why most JavaScript libraries have support for a dom-ready event, modern browsers have this as well (domcontentloaded) however for wide browser support it's a little trickier to do it for yourself (well, not that difficult, 3 or 4 different ways I think.)
The element does not exist yet when that script is being evaluated. Put it in the body's onload handler or something instead, so it executes once the DOM is in place.
An example of how to do this without touching any markup:
function callWhenLoaded(func) {
if (window.addEventListener) {
window.addEventListener("load", func, false);
} else if (window.attachEvent) {
window.attachEvent("onload", func);
}
}
callWhenLoaded(function() { makeCurrent("undergraduate"); });
The DOM is not fully loaded if you run makeCurrent in your head. You should put that script after your <li> tags.
Your code can be optimized: you can set a class attribute directly with current.className = 'current';.
The reason is that your script is being run before the page load is complete, and therefore before the DOM is populated.
You need to make sure you only call the function after page load is complete. Do this by triggering it using document.onload() or an onload event on the body tag.
After all the technical answers have been spewed out already, I'm going to skip all those which it very well could be and go for some of the more obvious ones I've run into which have caused me to facepalm once I've realised:
Typo in the identity
The identity isn't what you think it is because it's being generated or partially generated by the web framework you're using i.e. in ASP.NET you could set the client id to "MyControl" only to find that by the time it is rendered in the client it's "Page_1$Control_0$MyControl$1"
You've prepended it with a # in one or more of the incorrect places, for instance, although you're not using jQuery in your example if the object id is MyControl, in jQuery and CSS you reference it using #MyControl, but in the actual id of the object, you didn't use #. In document.getElementById() you don't use a # like you would in jQuery and CSS, but you may have used it inadvertently.
You've set the name element in the control instead of the id.
As other people have mentioned though, it could be down to not waiting for the element to be available at the time you're referencing it.
Please excuse my ignorance I am not very familiar with JavaScript and have been tasked with repairing a bug by a developer no longer at the company.
The onclick works perfectly in FireFox, however in IE 7&8 (the only ones we test for), it appears to run through the onclick functions properly, then instead of the data being submitted to the form URL in goStep3(), it runs through every onclick on the page, with href="#" then finally submits with incorrect information as the variable has been overwritten 50 times.
view
EDIT:
When I run trackSponsor(62, 64265); goStep3(1896, 64265, 0); return false; in the Developer Tools in IE8 I get an error of returning false outside of a function....removing that it works just fine.
Is the line that I believe is causing the problems?
trackSponsor() is working properly and returns false
goStep3() is quite a large function however it works by retrieving values from 4 other functions within, assigning the values to a URL within theAction
It completes the function by EDIT:
var yr = $("#find-yr").attr('value');
var me = $("#find-me").attr('value');
var mo = $("#find-mo").attr('value');
var keywords = $("#find-keywords").attr('value');
var theAction = PATH_BASE+'find/step3/'+p_term+'/'+p_id+'/'+p_l_id+'/';
document.forms['FindForm'].action = theAction;
document.FindForm.submit();
return true;
I have tried returning false from this function, as well as changing the document.FindForm.submit() to the 'correct' syntax of document.forms['FindForm'].submit() and it still does not submit until running through all of the other onclick s on the page.
Thanks in advance!
Notes:
jQuery is being used as well.
Javascript is not throwing any errors.
This works fine in FireFox
I can see it going through all of the other functions in the other onclicks using Developer Tools and stepping through the page it does not submit the results of goStep3 until it has gone through all of the other onclick functions on the page.
"posting my earlier comment as an answer"
I see a lot of jQuery being used with attribute selectors, so plz check the code against those.
EDIT:
I noticed ur unfamiliar with JavaScript... so in-case u didnt know, a jQuery selector, will select all tags matching a certain "selector-filter" and perform a certain action on them... so if there is a selector that selects all A tags with a href attribute (or maybe another common attribute between them...) then that would be the cause of your problem.
EDIT: -after you posted your answer -
glad you found an answer...
though it is alittle werid,
cause according to your question it goes through "every element with href="#" ...
However According to msdn, Event bubbling simply passes these unhandled events to the parent element for handling. not through "similar" tags :)
oh well..nothing is logical when it comes to IE
I would start by removing "return false;" from the onClick event since it really isn't doing anything.
try changing
href="#"
with
href='javascript:void(0)' .
I can't say for sure where things are going wrong, but I discourage using a form's name attribute to reference it like you have done here:
document.forms['FindForm'].action = theAction;
document.FindForm.submit();
Why not try the following jQuery:
$("form:FindForm").action = theAction;
$("form:FindForm").trigger("submit");
You should also check that $("form:FindForm") is indeed referencing the desired form element.
The problem was called because of how IE uses the bubble! Thanks all for your help, I have included the code solution to be placed in goStep3().
var browserName = navigator.appName;
if (browserName == "Microsoft Internet Explorer") {
window.event.cancelBubble = true;
}