I am trying to remove an element on AJAX success which was loaded and attached to the document during a previous AJAX call.
My code looks something like this:
$("#jobs-table-body").on("click", ".one-rc-button", function() {
var ctx = $.parseJSON($(this).siblings(".context").html());
$("#one-rc-candidate-id").val(ctx.candidateId);
$("#one-rc-job-id").val(ctx.jobId);
var loader = $("#wrapper").loader();
$.post($("#one-rc-form").attr("action"), $("#one-rc-form").serialize(), function(result) {
loader.remove();
if(result.success) {
// This works and returns 1
alert($("#candidate-row-" + result.rejectedCandidateId).length);
// This doesn't seem to be doing anything
$("#candidate-row-" + result.rejectedCandidateId).remove();
} else {
//$("#one-jc-messages").html(result.error);
}
});
});
The elements .one-rc-button and #candidate-row-<candidateId> were loaded by a previous AJAX call and they are attached to the document as I can very well see them on my page.
Now, on click of the previously generated .one-rc-button, I trigger a second AJAX call (which works fine) and on result.success, I want to delete the #candidate-row-<candidateId> (which is within the previously generated parent element).
The alert works and returns 1. So I know for sure that the selector is fine and it is matching one unique element.
What I don't understand is why it is unable to remove the element from the page.
Observations
I use Firefox 10.0.2 where this problem is reproducible.
On IE 8, it works (element gets removed)
On debugging the script on Firebug, I can verify that I have got a handle to the right eleemnt.
Try using FireBug to set a breakpoint on that line so you can see exactly what it's getting from that selector. Ideally break up the statement first, like this:
var unwantedDiv = $("#candidate-row-" + result.rejectedCandidateId);
unwantedDiv.remove(); // <-- Set a breakpoint on this line
You can then look at the unwantedDiv variable in the watch pane on the right of the firebug debugger and see what it is, what methods it has/has not got etc. I would assume that you are not getting back exactly what you think you are, possibly because of how you attached the div after the previous AJAX call. More information about JavaScript debugging with FireBug here.
Another option is to turn on strict warnings in the firebug console and see if you get any 'undefined method' errors, which don't stop the show on FireFox, but just bounce you out of that function. Do you get an error in IE?
Solved it by a really ugly workaround. I am still not sure what causes this behaviour.
if(result.success) {
var removeThis = $("#candidate-row-" + result.rejectedCandidateId);
removeThis.remove();
removeThis = $("#candidate-row-" + result.rejectedCandidateId);
if(removeThis.length != 0) {
removeThis.remove();
}
}
Now it works on both Firefox and IE.
Related
I would like to be able to use the dc.js select menu (dc.selectMenu) in such a way that when I click on an element it gets the value of said element and that becomes the value of the select, once selected it should refresh the data as it normally would if you had just selected in the first place.
The problem I'm having is that I can set the value, but dc.redrawAll() seems to do nothing for me so I think I must be filtering wrongly, but I can't find much information online regarding how to do it other than simply using the filter method (not onclick).
I have tried to set the destination to whatever data-destination is which appears to be working, the value of the select does update when I check with console.log to check the value of the select menu, I then use the dc.redrawAll() function expecting it would filter based on the select option but it does nothing (not even an error in the console)
My function so far is looking like:
function select_destination(ndx) {
var destination_dim = ndx.dimension(dc.pluck('destination'));
var destination_group = destination_dim.group();
var destination = null;
document.addEventListener('click', function(e) {
if (!e.target.matches('.open-popup-link')) return;
e.preventDefault();
var destination = e.target.getAttribute('data-destination').toString();
document.getElementById('select-destination').value = destination;
dc.redrawAll();
});
dc.selectMenu('#select-destination')
.dimension(destination_dim)
.group(destination_group)
.filter(destination);
}
I would expect the graphs to update based on the select option but nothing happens, and I get no error message to go off either.
I suspect I'm using dc.redrawAll() wrongly as if I go to the console and type dc.redrawAll(); I get undefined but I'm really at a loss now and the documentation isn't really helping me at this point so I don't know what else to do.
they are bits of your code that I don't quite understand, for instance why do you have have filter(destination /*=null */)
anyway, So you want to filter the select menu? you can call directly the replaceFilter function with the value, as done in the source code:
menu.replaceFilter(destination);
dc.events.trigger(function () {
menu.redrawGroup();
});
See the source code for the full example of how it's done
https://dc-js.github.io/dc.js/docs/html/select-menu.js.html#sunlight-1-line-129
as for why it doesn't work, I have had some surprising results mixing d3 with pure dom js. Try to rewrite your even handler in d3, eg
d3.select('#select-destination').property('value', destination);
it's possibly that changing the value on the dom directly isn't triggering the change event.
My experience with d3 is that it works better to change the underlying data (call directly filter functions or whatever you want to do) and let dc redraw the needed rather than manipulating the dom directly
I'm building a proof of concept test with CasperJS and I'm trying to wrap my head around when things are available and when they are not.
I'm a bit fuzzy on why evaluate() is required and why one cannot just get a page and go to town with document.querySelectorAll(), but that ends up giving me a nodeList with a length of zero... even after casper.echoing out the HTML and SEEING plenty of matching selectors.
Right now, I'm trying this:
var tile;
var pid;
casper.waitForSelector('.m-product-tile', function() {
tile = this.evaluate(function() {
return __utils__.findOne('.m-product-tile');
});
pid = this.evaluate(function()
return __utils__.findOne('.m-product-tile').getAttribute('data-pid');
});
//do cools stuff like click() on tile and make sure the URL has the pid in it
});
But this feels wrong as I am not sure __utils__.findOne() will always return the same element.
I'd love to be able to do this instead:
pid = tile.getAttribute('data-pid');
But when I attempt that, I get an error:
uncaughtError: TypeError: 'undefined' is not a function (evaluating 'tile.getAttribute('data-pid')')
Did tile somehow cease to be a DOMNode with a getAttributes method? Using typeof tile, it still thinks it's an object. I echoed out the DOMNode and it has a getAttributes key.
The code in the first example DOES work with getAttribute... so why does tile morph into something that no longer has a getAttributes method?
http://casperjs.readthedocs.org/en/latest/modules/casper.html#evaluate provides a pretty good answer... but still, I'd like to know why, if what the page is passing back, is a DOMNode, why can't I treat it like one?
(sorry for my bad english)
I have a big problem with which I've been beating me for several days but to which I do not find any solution, even while going to excavate very far in subjects on known forums (and less known).
I develop a small application in Javascript which must recover an array of links. I open these links one by one in the same page, and I click on a button (which posts a name), then I check after a small lapse of time that the name is well posted and corresponds to that present on the page (in a fixed div). At this time, I turn over on the basic page, then I start the script again with the second link contained in the array.
The problem is that the code is not carried out anymore after the window.load() function.
I test the code on Google Chrome (in the Javascript console) and it turns over me an error: “Uncaught ReferenceError: init is not defined … onload ".
I hope that you will be able to help me to find how to once carry out the code with the launching of the page it is launched since each bond opens a page in the relationship page.
Before, I had tested in a popup with the function window.open () (without “_parent”) and I wanted to close it thanks to window.close () function, but the code did not include/understand where to act since the remainder of the code was to now deal with the popup and not of the page on which the code was carried out at the beginning.
Here's the code :
//Here i get the links in an array
function recupHref(){
var lesHref = new Array();
var lesLiens = document.getElementsByTagName("a");
for(var i = 0; i < lesLiens.length; i ++)
if(lesLiens[i].parentNode.getAttribute("class") == "pubrhead-text-right")
lesHref.push(lesLiens[i].getAttribute("href"));
return lesHref;
}
var resultat = recupHref(); //I store them in a variable
//The main function which open the links one by one
//The while loop allows us to know if were subscribed or not
var o = function openLinks(){
for(var leIndex = 0; leIndex < resultat.length; leIndex ++){
window.open(resultat[leIndex], "_parent");
//Do i use window.load instead of DOMContentLoaded ?
addEventListener("DOMContentLoaded", function() {
document.getElementById("enbut").click();
var pseudo = document.getElementById("nameho").innerHTML;
var pseudok = document.getElementsByClassName("pname")[0].textContent;
});
while (pseudo === pseudok) {
!(window.open("http://page-with-links.html", "_parent"));
};
}
}
I thank you in advance, and I hope that you will include/understand my problem.
Here is a little draw to explain better than words :
In other words, just what i need is that : store links (done) --> Open the link --> Click on the button (done) --> Check if the 2 names are the same --> Came back to the first page/close popup/ (or go directly to the seconde link in the array) --> do this for the 2nd link, etc, etc.
Good day/evening.
I am using the following jQuery plugin :
http://pvdspek.github.com/jquery.autoellipsis/, and in general it works very well.
The problem comes when I need to update the text of the element. One would assume that changing the text of the element and calling the plugin again would perform the same action the initial call performed.
But, as can be seen in this fiddle - it doesn't.
The code is very simple
var container = $(".container");
container.text("This is a long text that should have text ellipsis");
//this works fine
container.ellipsis();
$("button").click(function()
{
container.text("This is the modified text that should also have ellipsis");
//this doesn't work
container.ellipsis();
});
The only way I could make it work is by deleting the data stored on the element, and by this
making the plugin run "from scratch".
any ideas?
Clear the data stored by autoellipsis: container.data('jqae', null);
var container = $(".container");
container.text("This is a long text that should have text ellipsis");
//this works fine
container.ellipsis();
$("button").click(function()
{
container.data('jqae', null);
container.text("This is the modified text that should also have ellipsis");
//this doesn't work
container.ellipsis();
});
Since extensions can not access unsafeWindow, like Firefox can, to hook into DOM scripts am I looking for other ideas so I come to SO for help!
How about using some code to inject into DOM and sending the intercepted response to a background page, which then does some initial processing before calling a content script for final processing. When done, it answers to the background with a modified response, or the original (it depends), and the background page sends the response back to DOM which handles it to the DOM script response function.
There is just one problem with this, a background page cant communicate with the DOM.
I did a small test with injecting some code, where I output something to the console and an alert. The result wasnt good, as the alert fired but the console was empty - not even an error, which makes me wonder - what console received the output ?
function injectCode(fn){ // Executing an anonymous script
var script = document.createElement('script');
script.type = 'application/javascript';
script.textContent = '(' + fn + ')();';
document.documentElement.appendChild(script); // run the script
document.documentElement.removeChild(script); // clean up
}
var code = function(){
console.log('dom',window);
alert('code injected');
}
injectCode(code);
I also tried addEventListener, with DOMAttrModified DOMSubtreeModified DOMNodeInserted, on DOM elements that change when the DOM ajax response is fully parsed but all failed to fire.
Am I trying to do the impossible, by any means ?
Before continuing, make sure that you know the differences between the script contexts in an extension.
To inject a script from the background page, you have to execute a Content script, which on his turn injects the script as mentioned in your question / here.
Examples (using chrome.tabs.executeScript):
// null = current active tab
// Simple code, background:
chrome.tabs.executeScript(null, {
code: [
'var s = document.createElement("script");',
's.textContent = "console.log(window);";',
'(document.head||document.documentElement).appendChild(s);',
's.parentNode.removeChild(s);'
].join('\n')
});
I can imagine that this method is not doable for a big chuck of code. For a set of pre-defined scripts, you can then use two scripts: the code itself, and a helper script:
// config.js
var fn_code = function() {
console.log(window); ....
};
// helper.js
var s = document.createElement('script');
s.textContent = '(' + fn_code + ')();';
(document.head||document.documentElement).appendChild(s);
s.parentNode.removeChild(s);
// Background:
chrome.tabs.executeScript(null, {file: 'config.js'}, function() {
chrome.tabs.executeScript(null, {file: 'helper.js'});
});
Note: I did not directly link to "config.js", because that complicates the use when using manifest version 2, see "web_accessible_resources".
The previous method only shows how to execute code in one direction (background -> page). If there's a need to activate a background's function from the injected script, you have to define and listen to a custom event handler. See this answer + demo.
Because the code is injected, thus runs in the scope of the page, you have to check the console at the page.
When chrome.tabs.executeScript fails to execute the Content script (eg. because the extension does not have the permission to access a certain page), an error is logged at the console in the background page. This console can be accessed by following these steps.