Pass json through click event to jQuery function - javascript

I have this old "closed" system where it runs IE in its own container, meaning I have to code like a caveman in many cases because I can't use any browser developer tools/console to x-ray the objects being returned from the remote system.
Now, the specific function I'm looking at is a callback from a third party (it gets complicated) that returns what I am willing to bet is a standard JSON object.
function core_OnUeDeltaItemsUpdate(dataType, oData)
{
if (dataType == "Units")
{
// Bail if dispatch report xml hasn't been loaded yet.
if (oXml == null)
return;
..... does lots of stuff
// Reload the content in case any of our displayed units changed
processUeDelta.click();
}
}
... at the bottom of the page
<button style="display:none;" type="button" id="processUeDelta"/>
and the attached javascript file that I was hoping would use jQuery
$(function(){
$("#processUeDelta").click(function(){
var i = 0;
alert(this.ueDelta);
for(var propertyName in this.ueDelta)
{
i++;
alert("property " + i + ": " + oData[propertyName]);
}
});
});
Now, currently the last function that binds itself to the hidden button cannot parse oData. I'm stuck on two things here.
I'm not sure how to pass the oData object to the attached eventhandler
I'm not too keen on this design, perhaps there is another way were I can take out the intermediary button so I can then process the JSON data object oData.
Points of note:
This is based on a data pump, so this callback is being called on an average of 5s.
I am limited to using jQuery 1.7.1
I cannot see the object, my browser cannot act as a test harness, there are too many moving parts for me to be able to test it from outside the application.

You can replace the core_OnUeDeltaItemsUpdate function with your own and then call the original core_OnUeDeltaItemsUpdate function. In your jQuery file do something like this
$(document).ready(function(){
window._core_OnUeDeltaItemsUpdate = core_OnUeDeltaItemsUpdate;
window.core_OnUeDeltaItemsUpdate = function(dataType, oData){
// pass the parameters into the original function
_core_OnUeDeltaItemsUpdate(dataType, oData);
// do whatever you need to do with oData
var i = 0;
alert(this.ueDelta);
for(var propertyName in this.ueDelta)
{
i++;
alert("property " + i + ": " + oData[propertyName]);
}
}
});

Related

phantomJS how to get answer from JS scripts which starting after the page have loaded

I'm looking for a solution for that question.
The site load several JS scripts after page have loaded, it's working well, the page get the response from the scripts and render it to site page.
But the scripts return JSON and I want to get this response in JSON, not from generated page. It's a more faster to use the script's answer than use selectors and cycles for get the information from page.
I try to use page.onResourceReceived() but it's get me only analytics information, filenames stock and response sizes;
How can I get the body of this response ?
If I have understood your requirement correctly, you may try using window.callPhantom at the web page end to pass the data as an Object and receive the data through page.onCallback eventlistener at PhantomJS scope.
http://phantomjs.org/api/webpage/handler/on-callback.html
Excerpt:
This callback is invoked when there is a JavaScript window.callPhantom call made on the web page. The only argument passed to the callback is a data object.
Note: window.callPhantom is still an experimental API. In the near future, it will be likely replaced with a message-based solution which will still provide the same functionality.
Although there are many possible use cases for this inversion of control, the primary one so far is to prevent the need for a PhantomJS script to be continually polling for some variable on the web page.
Example:
WebPage (client-side)
if (typeof window.callPhantom === 'function') {
window.callPhantom({ hello: 'world' });
}
PhantomJS (server-side)
page.onCallback = function(data) {
console.log('CALLBACK: ' + JSON.stringify(data)); // Prints 'CALLBACK: { "hello": "world" }'
};
Additionally, note that the WebPage#onCallback handler can return a data object that will be carried back as the result of the originating window.callPhantom call, too.
Example:
WebPage (client-side)
if (typeof window.callPhantom === 'function') {
var status = window.callPhantom({ secret: 'ghostly' });
alert(status); // Will either print 'Accepted.' or 'DENIED!'
}
PhantomJS (server-side)
page.onCallback = function(data) {
if (data && data.secret && data.secret === 'ghostly') {
return 'Accepted.';
}
return 'DENIED!';
};

How to pass data from one HTML page to another HTML page using JQuery?

I have two HTML pages that work in a parent-child relationship in this way:
The first one has a button which does two things: First it requests data from the database via an AJAX call. Second it directs the user to the next page with the requested data, which will be handled by JavaScript to populate the second page.
I can already obtain the data via an ajax call and put it in a JSON array:
$.ajax({
type: "POST",
url: get_data_from_database_url,
async:false,
data: params,
success: function(json)
{
json_send_my_data(json);
}
});
function json_send_my_data(json)
{
//pass the json object to the other page and load it
}
I assume that on the second page, a "document ready" JavaScript function can easily handle the capture of the passed JSON object with all the data. The best way to test that it works is for me to use alert("My data: " + json.my_data.first_name); within the document ready function to see if the JSON object has been properly passed.
I simply don't know a trusted true way to do this. I have read the forums and I know the basics of using window.location.url to load the second page, but passing the data is another story altogether.
session cookie may solve your problem.
On the second page you can print directly within the cookies with Server-Script tag or site document.cookie
And in the following section converting Cookies in Json again
How about?
Warning: This will only work for single-page-templates, where each pseudo-page has it's own HTML document.
You can pass data between pages by using the $.mobile.changePage() function manually instead of letting jQuery Mobile call it for your links:
$(document).delegate('.ui-page', 'pageinit', function () {
$(this).find('a').bind('click', function () {
$.mobile.changePage(this.href, {
reloadPage : true,
type : 'post',
data : { myKey : 'myVal' }
});
return false;
});
});
Here is the documentation for this: http://jquerymobile.com/demos/1.1.1/docs/api/methods.html
You can simply store your data in a variable for the next page as well. This is possible because jQuery Mobile pages exist in the same DOM since they are brought into the DOM via AJAX. Here is an answer I posted about this not too long ago: jQuery Moblie: passing parameters and dynamically load the content of a page
Disclaimer: This is terrible, but here goes:
First, you will need this function (I coded this a while back). Details here: http://refactor.blog.com/2012/07/13/porting-javas-getparametermap-functionality-to-pure-javascript/
It converts request parameters to a json representation.
function getParameterMap () {
if (window.location.href.indexOf('?') === (-1)) {
return {};
}
var qparts = window.location.href.split('?')[1].split('&'),
qmap = {};
qparts.map(function (part) {
var kvPair = part.split('='),
key = decodeURIComponent(kvPair[0]),
value = kvPair[1];
//handle params that lack a value: e.g. &delayed=
qmap[key] = (!value) ? '' : decodeURIComponent(value);
});
return qmap;
}
Next, inside your success handler function:
success: function(json) {
//please really convert the server response to a json
//I don't see you instructing jQuery to do that yet!
//handleAs: 'json'
var qstring = '?';
for(key in json) {
qstring += '&' + key + '=' + json[key];
qstring = qstring.substr(1); //removing the first redundant &
}
var urlTarget = 'abc.html';
var urlTargetWithParams = urlTarget + qstring;
//will go to abc.html?key1=value1&key2=value2&key2=value2...
window.location.href = urlTargetWithParams;
}
On the next page, call getParameterMap.
var jsonRebuilt = getParameterMap();
//use jsonRebuilt
Hope this helps (some extra statements are there to make things very obvious). (And remember, this is most likely a wrong way of doing it, as people have pointed out).
Here is my post about communicating between two html pages, it is pure javascript and it uses cookies:
Javascript communication between browser tabs/windows
you could reuse the code there to send messages from one page to another.
The code uses polling to get the data, you could set the polling time for your needs.
You have two options I think.
1) Use cookies - But they have size limitations.
2) Use HTML5 web storage.
The next most secure, reliable and feasible way is to use server side code.

JavaScript variable carry an ID that I need to use in a Html.ActionLink

I have a JavaScript variable in my jQuery code that contains an ID that I need to use in my Html.ActionLink but it's not working:
#(Html.ActionLink("Genomför", "AnswerForm", "AnswerNKI", new {id = goalcard.Id},null))
I get: 'cannot resolve symbol "goalcard"', and the reason is that goalcard is a JavaScript variable.
This is what it looks like:
$.post('#Url.Action("Search", "SearchNKI")', data, function (result) {
$("#GoalcardSearchResult tbody").empty();
result.forEach(function(goalcard) {
$("#GoalcardSearchResult tbody").append(
$('<tr/>', {
// steg Create a row for each result
html: "<td>" + goalcard.Name +
"</td><td>" + goalcard.Customer +
"</td><td>" + goalcard.PlannedDate +
"</td><td>" + goalcard.CompletedDate +
"</td><td>" + '#(Html.ActionLink("Genomför", "AnswerForm", "AnswerNKI", new {id = goalcard.Id},null))' + "</td>"
}));
});
});
I have been testing for while now and I almost found a solution and it looks like this:
#(Html.ActionLink("Genomför", "AnswerForm", "AnswerNKI",null, new {id = "mylink"}))
then I made a new function:
$('#mylink').click(function (goalcard) {
var id = goalcard.Id;
this.href = this.href + '/' + id;
});
This should work, but what happens is that I have to use this click function inside the forEach loop to be able to reach to goalcard variable. and If I put it inside the forEach, this Click function will get executed many times depending on how many goalcard there are.
So the result would be /AnswerNKI/AnswerForm/1/2 if there are two goalcards.
or maybe /AnswerNKI/AnswerForm/1/2/3/4/5 if there are five goalcards.
But it should be /AnswerNKI/AnswerForm/1
it basically adds up.
Another problem is that all other rows have /AnswerNKI/AnswerForm/ so only the first row basically gets an id.
I have no idea how to find a solution to fix that.
Any kind of help is very appreciated.
Thanks in advance
This isn't a solution to the specific problem you're having. But it looks like you're using jquery to update part of your page.
If so, have you considered using a callback which returns html generated by a PartialView, and just doing a replace within the javascript callback? That's a pattern I use a lot. It allows you to use the MVC engine, components and design tools.
Here's an example of something I do:
$("form.unscoped_filter").live("submit", function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
error: function (a, b) {
debugger;
},
success: function (result) {
$("div#targetID").html(result);
bindExtenders();
}
});
return false;
});
This particular example intercepts a postback from a particular class of forms and passes it on to the website where it's processed by my MVC app. The target method and controller are set, per usual MVC design approaches, in a BeginForm block. The target method processes data and returns a PartialView which translates that data into html, which in turn is sent to the success callback in the jquery block. There it's used to replace the html within the target div. While there are more parts in play (e.g., the javascript, the MVC method, the PartialView), separating things this way lets each part play to its unique strengths: jquery is wonderful at manipulating the DOM, MVC methods are great at manipulating/processing requests for html, and PartialViews are a great tool for laying out and generating html.
This is a pretty flexible and powerful approach once you get the hang of it. In particular, you can pass parameters into the jquery block from the ActionLink by using html5 techniques. For example, you can add a "data-someParamName=..." to the html attributes of the ActionLink call, and then extract the parameter value within the javascript block doing something like:
var pagerCode = $(this).attr("data-someParamName");
That, in fact, is how I control which particular div gets updated in the success callback function.
Again, this doesn't answer your specific question so much as suggest a different way of tackling what I think you're trying to do. Good luck!

Fill gridview using javascript on selected tree node value

my requirement is to get the result in gridview based on the treeview node selection using javascript i.e. client scripting. Currently the same can be achieved using server side scripting, but i want to do this without postback and without using selectednodeindexchanged event. Pls. help me to solve this problem.
The solution is quite involved but goes something like this:
Use the Page.GetCallbackEventReference method to make an XmlHttpRequest back to the server and retrieve a json object that will be used to populated the grid.
See the System.Web.Script.Serialization namespace for pointers on how to convert your objects to JSON.
Create a JavaScript closure to encapsulate your grid update logic. Something like:
var vm = {
someField: 'test',
init: function() {
},
update: function(data) {
var grid = document.getElementById('yourGrid');
// loop through the data and set the innerHTML on the cells to whatever your data is.
}
}
setTimeout(function() {
vm.init();
}, 100);
// In the aspx/ascx
//when the callback completes convert the json to an object like this
var d = eval('(' + data + ')');
//call update on your object
vm.update(data)

Javascript callback function issue

Background
I'm writing an asynchronous comment system for my website, after reading plenty of tutorials on how to accomplish this I started building one from scratch. The comments are pulled using a JSON request and displayed using Javascript (jQuery). When the user adds a new comment it goes through the hoops and finally is sent via AJAX to the backend where it's added to the database. In the success section of the AJAX request I had the script empty the comments, then repull the new list (including the new post) and redisplay them.
Problem
While that was all nice, since it's making the page much shorter, then much longer it messes up where the user is viewing the page. I wanted to have it readjust the page back down to the end of the comment list (where the add comment form is). It also re-enables the add button, which was disabled when the clicked it to prevent impatient people from spamming.
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
While this worked all well and good in theory, it seemed that the browser was getting ahead of itself and processing the window.location before the getComments function was done. So I read a little more and googled it and it seemed people were saying (for similar problems) to use callback functions, so I came up with this:
$('#commentList').empty();
getComments('blog', $('input#blogId').val(), function() {
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
This generates no javascript errors according to FireFox, but nothing within the callback function is working, it's not re-enabling the button nor changing the window.location.
Any ideas? Better ways to go about it? Do I have a glaring typo that I can't seem to see?
Thanks!
Update
I was under the impression the callback functions were a standard thing you could use.
function getComments(type, id)
{
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
});
}
This is called on document ready. Pulling all the comments and displaying them inside the #commentList div. When the user submits his/her comment it performs an AJAX request to a PHP script that adds the new comment to the database, upon success of this I have this:
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
Deletes all the comments from the page.
Uses JSON to request the comments again (including the users new one).
Moves the page to the #addComment anchor, which is where their new comment would be displayed.
Re-enables the add comment button.
The problem is that the browser does the window.location line before the getComments function is done rendering all the comments, so as the page grows the user isn't looking anywhere near their new comment.
I expect here the problem is your getComments() function (for which more detail is required). You're supplying a third argument being a callback but does the function actually use a callback? What is it doing?
Certain jQuery functions provide callbacks but this isn't an automatic feature. If you're waiting for a user to type a comment you need to trigger the relevant event when they click "Done" or whatever they do.
Ok, try this:
function get_comments(type, id, callback) {
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++) {
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" ) {
legend.text((x+1) + ' - ' + data[x].name);
} else {
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
if (typeof callback != 'undefined') {
callback();
}
}
});
}
Note: the difference here is that a third argument is supplied to get_comments() which is a callback that'll be called at the end of your $.getJSON() callback. That'll give you the proper ordering you want.
I might also suggest not constructing the HTML like that but including it in your page and hiding/unhiding it as necessary. It tends to be much more performant that dynamic HTML and have less issues (eg new HTML, unless you use $().live() will not have relevant event handlers).
Edit: Made the callback optional as per the comments. With the above code you can call the function without or without the callback.
Simple. Re-enable the button and go to the anchor after you receive the request and process the information. Like so:
function getComments(type, id)
{
// ADDED
$('#commentList').empty();
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
// ADDED
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
}
Personal opinion: rather than fetching all comments, why not fetch comments from a certain date? When you load the page, include a server time in the response. The Javascript uses this to query behind the scenes (to automatically check for new comments). The JSON response includes a new server time, which is used in the next response.
How would you handle deleted comments? Easy: have a deleted_on column in your database table, query it, and spit that out in the JSON response along with new posts.
Suggestion: instead of #addcomment, ID comments by timestamp.

Categories

Resources