I am writing a single page web application for Microsoft SharePoint.
I'd like to pull in content with $.get(), but I've run into a bit of a catch 22.
If I pull in the content like this:
function getLocalPage(url, callback) {
$.get(url, function(data) {
var $page = $(data).filter('.tileContent').html();
callback($page);
});
}
I get the node I'm looking for, but my script tags have been stripped out.
If I pull in content like this:
(reference to: jquery html() strips out script tags )
function getLocalPage(url, callback) {
$.get(url, function(data) {
var dom = $(data);
dom.filter('script').each(function(){
$.globalEval(this.text || this.textContent || this.innerHTML || '');
});
var $page = dom.filter('.tileContent');
callback($page);
});
}
The javascript embedded in SharePoint blows my page up, and seems to cause a full postback.
Is there any way to get only the node I would like, with the script tags intact?
Can't seem to have it both ways.
Rather than the shorthand jQuery method .get(), try .ajax() with dataType: 'html'
The .ajax() documentation says of dataType: 'html' :
"html": Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.
It also says :
"If 'html' is specified, any embedded JavaScript inside the retrieved data is executed before the HTML is returned as a string."
The emphasis here is on the word "before" meaning that the embedded JavaScript, when executed, cannot act directly on the HTML with which it is delivered (or a resulting DOM-fragment), though it can act directly on the existing DOM, prior to fragment insertion.
However, any functions included in the embedded JavaScript do indeed become available to act on the HTML/DOM-fragment and the DOM at large, if called later. The first opportunity to call such functions is in the .ajax() success handler (or chained .done() handler).
Unless extraordinary (and potentially messy) measures are taken, the success handler (or any functions called by it) will need prior "knowledge" of the names of any functions that are delivered in this way, otherwise (realistically) they will be uncallable.
I'm not sure about code delivered inside a $(function() {...}); structure, which may execute when the current event thread has completed(?). If so, then it could potentially be made to act on the delivered HTML/DOM-fragment. By all means try.
With all that in mind, try the following approach, with appropriately phrased JavaScript in the response.
function getLocalPage(url, callback) {
$.ajax({
url: url,
dataType: 'html',
success: function(data) {
callback($(data).find('.tileContent'));
}
});
}
or better :
function getLocalPage(url, callback) {
$.ajax({
url: url,
dataType: 'html'
}).done(function(data) {
callback($(data).find('.tileContent'));
});
}
Notes:
I changed .filter() to .find(), which seems more appropriate but you may need to change it back.
Your final version may well have further .ajax() options.
Related
I am developing a page that reads the source of another page and I need to extract certain information out of that page. I currently have the project snagging the live source with the data however I cannot for the life of me figure out how to convert this string into a document.
My rationale for using a document is that I need to use getElementById etc to get the value of these items.
What have I tried?
Assigning the HTML to an invisible div on my page. This kind of works though it doesn't render the entire HTML string and provides a "shorter" rendition of this page.
Manually finding the substrings. As you can imagine this is a crappy way to do things and provides very unreliable results.
DOM parser to convert the doc and then query it but that fails miserably.
Any assistance at all would be seriously appreciated.
pertinent code:
$.ajax({
method: "GET",
dataType: '',
crossDomain: true,
xhrFields: {
withCredentials: true
},
success: function(res) {
//shows the entire source just fine.
console.log("Value of RES: " + res);
bootbox.hideAll();
//shows a "truncated" copy of the source
alert(res);
$("#hiddendiv").html(x);
var name = document.findElementById("myitem");
alert(name);
},
Create a hidden IFRAME on your document. Then set the contents of that IFRAME to the HTML that you want to query. Target that IFRAME with your javascript when you do your querying. See How can I access iframe elements with Javascript? to understand how.
Another (probably better) option, is to use jQuery. jQuery allows you to create HTML, manipulate it, and query against it in memory. Querying DOM elements in jQuery is even easier than it is in pure javascript. See: http://jquery.com/.
//Get a jQuery object representing your HTML
var $html = $( "<div><span id='label'></span></div>" );
//Query against it
var $label = $html.find( "#label" ); //finds the span with and id of 'label'
is there an easy way to use the g:message functionality in a dynamic way in Javascript, e.g.
function get_i18n( myAttr ) {
return "${message(code:'" + myAttr + "')} ";
}
so that I can perform the function call
pl_get_i18n( "xyz" )
for the predefined i18 attribute xzy ?
Like here, but dynamic: https://stackoverflow.com/a/8296812/1779814
PS: The JS code is included in the GSP file.
The short answer is "no". GSP tags can only be executed on the server-side, not by the browser (i.e. JavaScript).
However, I would expect there is at least one Grails plugin that does the following:
creates a JavaScript object containing the messages defined in your messages*.properties file(s)
provides a JavaScript function that enables you to resolve messages from this object
So although it's not possible to execute GSP tags in the browser, it doesn't seem terribly difficult to provide equivalent functionality in JavaScript. I would be amazed if there isn't already a Grails plugin that does this.
Here is a very simplistic example of how you can use AJAX to fetch a message code from the server.
// AjaxMessageController.groovy
package example
import grails.converters.JSON
class AjaxMessageController {
def index() {
render [message: message(code: param.code)] as JSON
}
}
Then within your page you can just use an ajax call (jQuery based) in this example to look up a message code:
var someMessageCode = 'something.you.want';
$.ajax({
dataType: 'json',
url: '${createLinK(controller: "ajaxMessage", action: "index"}',
data: {code: someMessageCode},
success: function(data) {
window.alert(data.message);
}
});
I am successfully able to pass variables from code behind to javascript in IE, but not in firefox.
What I do is I have these public variables in my code behind:
public string passedVar = "";
and it gets assigned to a value in the page load event:
passedVar = "In code behind";
and then in the aspx page, inside a script block, I do this:
var clientVar = "<%= passedVar %>";
and then I am able to access it in other js files of that page just fine... in IE only!
If I am using javascript; however, that variable in the .js is showing up as "undefined"
I can find alternate values like hiddenfield, but I want to know why this is not working like it should!
thank you!
If you need to process data through Javascript, do an ajax call (sync or async) to an empty .aspx page (I mean code-behind only), get the data result on success event and process the data in the callback function.
Some code based on JQuery samples:
$.ajax({
type: "POST",
url: "http://myDomain/myPage.aspx",
data: "par1=val1&par2=val2",
async: false,
success: function( data ) {
/*
* data contains the myPage.aspx response
* it could be a single value or a comma-separated list of values
* initialize passedVar or whatever
*/
});
I'm very, very new to Javascript, and to web programming in general. I think that I'm misunderstanding something fundamental, but I've been unable to figure out what.
I have the following code:
function checkUserAuth(){
var userAuthHttpObject = new XMLHttpRequest();
var url = baseURL + "/userAuth";
userAuthHttpObject.open("POST",url,true);
userAuthHttpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
userAuthHttpObject.onload=function(){
if (userAuthHttpObject.readyState == 4) {
var response = json.loads(userAuthHttpObject.responseText);
return response; //This is the part that doesn't work!
}
};
userAuthHttpObject.send(params);
}
I would love to call it from my page with something like:
var authResponse = checkUserAuth();
And then just do what I want with that data.
Returning a variable, however, just returns it to the userAuthObject, and not all the way back to the function that was originally called.
Is there a way to get the data out of the HttpObject, and into the page that called the function?
Working with AJAX requires wrapping your head around asynchronous behavior, which is different than other types of programming. Rather than returning values directly, you want to set up a callback function.
Create another JavaScript function which accepts the AJAX response as a parameter. This function, let's call it "takeAction(response)", should do whatever it needs to, perhaps print a failure message or set a value in a hidden field and submit a form, whatever.
then where you have "return response" put "takeAction(response)".
So now, takeAction will do whatever it was you would have done after you called "var authResponse = checkUserAuth();"
There are a couple of best practices you should start with before you continue to write the script you asked about
XMLHTTTPRequest() is not browser consistent. I would recommend you use a library such as mootools or the excellent jquery.ajax as a starting point. it easier to implement and works more consistently. http://api.jquery.com/jQuery.ajax/
content type is important. You will have have problems trying to parse json data if you used a form content type. use "application/json" if you want to use json.
true user authorization should be done on the server, never in the browser. I'm not sure how you are using this script, but I suggest you may want to reconsider.
Preliminaries out of the way, Here is one way I would get information from an ajax call into the page with jquery:
$.ajax({
//get an html chunk
url: 'ajax/test.html',
// do something with the html chunk
success: function(htmlData) {
//replace the content of <div id="auth">
$('#auth').html(htmlData);
//replace content of #auth with only the data in #message from
//the data we recieved in our ajax call
$('#auth').html( function() {
return $(htmlData).find('#message').text();
});
}
});
Hey all. I was fortunate enough to have Paolo help me with a piece of jquery code that would show the end user an error message if data was saved or not saved to a database. I am looking at the code and my imagination is running wild because I am wondering if I could use just that one piece of code and import the selector type into it and then include that whole json script into my document. This would save me from having to include the json script into 10 different documents. Hope I'm making sense here.
$('#add_customer_form').submit(function() { // handle form submit
The "add_customer_form" id is what I would like to change on a per page basis. If I could successfully do this, then I could make a class of some sort that would just use the rest of this json script and include it where I needed it. I'm sure someone has already thought of this so I was wondering if someone could give me some pointers.
Thanks!
Well, I hit a wall so to speak. The code below is the code that is already in my form. It is using a datastring datatype but I need json. What should I do? I want to replace the stupid alert box with the nice 100% wide green div where my server says all is ok.
$.ajax({
type: "POST",
url: "body.php?action=admCustomer",
data: dataString,
success: function(){
$('#contact input[type=text]').val('');
alert( "Success! Data Saved");
}
});
Here is the code I used in the last question, minus the comments:
$(function() {
$('#add_customer_form').submit(function() {
var data = $(this).serialize();
var url = $(this).attr('action');
var method = $(this).attr('method');
$.ajax({
url: url,
type: method,
data: data,
dataType: 'json',
success: function(data) {
var $div = $('<div>').attr('id', 'message').html(data.message);
if(data.success == 0) {
$div.addClass('error');
} else {
$div.addClass('success');
}
$('body').append($div);
}
});
return false;
});
});
If I am right, what you are essentially asking is how you can make this piece of code work for multiple forms without having to edit the selector. This is very easy. As long as you have the above code included in every page with a form, you can change the $('#add_customer_form') part to something like $('form.json_response'). With this selector we are basically telling jQuery "any form with a class of json_response should be handled through this submit function" - The specific class I'm using is not relevant here, the point is you use a class and give it to all the forms that should have the functionality. Remember, jQuery works on sets of objects. The way I originally had it the set happened to be 1 element, but every jQuery function is meant to act upon as many elements as it matches. This way, whenever you create a form you want to handle through AJAX (and you know the server will return a JSON response with a success indicator), you can simply add whatever class you choose and the jQuery code will take over and handle it for you.
There is also a cleaner plugin that sort of does this, but the above is fine too.
Based on your question, I think what you want is a jQuery selector that will select the right form on each of your pages. If you gave them all a consistent class you could use the same code on each page:
HTML
<form id="some_form_name" class="AJAX_form"> ... </form>
Selector:
$('form.AJAX_form")