How to add an EventSource details page for Fullcalendar - javascript

I'd like to add a EventSource detail page to Adam Shaw's Fullcalendar. A use case for this page is that the user wants to change the URL of the source or change the color of the events belonging to this source. For now I am blocked by the fact that I don't know exactly how to retrieve the source object. Part of the problem is that as far as I know, sources do not have an ID.
Which is the proper function in which I should inject the EventSourceID into the source object?
Should this function be something similar to the addEventSource from $ROOT/src/common/Views.js?
UPDATE: I changed the text in question the source to EventSource, to make it clear. Also now I have one solution in my mind, let me know if it's intrusive:
make sure each source object has an ID property set. This could be done by adding a source normalizer function to fc.sourceNormalizers array.
create retrieveEventSource which takes an EventSourceID as an argument and returns the source. The implementation this would be similar to _addEventSource.
UPDATE: Already found a problem, function retrieveEventSource is private and I don't know how to expose it to the world outside FullCalendar. Also, I have no idea yet on how to implement the update function that should redraw /AND/OR/ refetch the events, after the source details have changed.

Well since you're the one that populates the calendar event data in the first place just use that data on the new page.
events: function (start, end, callback) {
$.ajax({
url: url,
data: "json-events.php",
success: function (data) {
callback([event0,event1,event2,.....])
},
dataType: /* xml, json, script, or html */
});
...
Just get the data on the other page outside the calendars api

Related

Using "onClick()" function inside an ajax function while continue using its success data?

So I want to create an on click function after successfully called an Ajax function, but I still want to use its original data for that on click function.
$.ajax({
URL: ......,
type: 'GET',
success: function (res) {
var Object = JSON.parse(res);
text = ''
// some code using Object to fix text
$('#someid').attr('href', '#')
$('#someid').text(text)
Now what I want is that someid item, when clicked on, will create a pop-up, change its original content, or something that continues using the var Object up there. I tried but can't find a way to put on click into that Ajax function.
Your question is vague to me. Please specify what you want to achieve. Im assuming you want to have a function called inside Ajax trigger that consumes Object variable value. If so, it's feasible for sure by creating a function doClick(ọbject) and then you can invoke it simply by doClick(obj); after making tweaks to Modal popup. But i dare to think there is misunderstanding in your approach. If you could add more details on this, i could suggest you a way to solve the issue.

What's the correct way to send Javascript code along with rendered HTTP to a client?

Mid development I decided to switch to server-side rendering for a better control amongst other benefits. My web application is completely AJAX based, no url redirecting, so the idea here is a website that builds itself up
I just couldn't figure out the proper way to send javascript events/functions along with the html string, or should all the necessary javascript always be preloaded in the static files?
Let's say client clicks a pre-rendered button 'open table'
The server will make a query, build the html table and send it back, but this table also needs javascript triggers and functions to work properly, how are these sent, received and executed?
There are a couple of articles that mention to not use eval() in Javascript, is there any way around this? I don't want to have to preload unnecessary events for elements that don't yet exist
The server is Python and the Client is Javascript/JQuery
Theoretical example :
Client Base Javascript :
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
eval(response.javascript()); //??
}
});
Python Server(views.py) :
def get_table(request):
data = {}
#String containing rendered html
data['html'] = get_render_table()
#String containing Javascript code?
data['javascript'] = TABLE_EVENTS_JAVASCRIPT
return HttpResponse(json.dumps(data),content_type='json')
Worth noting my question comes from an experimental/learning perspective
Update:
You can use jQuery.getScript() to lazy load JS. I think this solution is as close as you can get to run JS without using eval().
See this example:
jQuery.getScript("/path/to/script.js", function(data, textStatus, jqxhr) {
/* Code has been loaded and executed. */
console.log( data ); // Data returned
console.log( textStatus ); // Success
console.log( jqxhr.status ); // 200
console.log( "Load was performed." );
});
and "/path/to/script.js" could be a string returned from $.getJOSN response.
Also, the documentation for getScrippt() has examples on how to handle errors and cache files.
Old Answer:
Using .on() attaches events to current and future DOM elements.
You can either attache events prior to DOM insertion or attache event after DOM insertion.
So in your example you can do something like:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
var code = $(response.html);
code.find(".elementToFind").on("click", function (){
// Code to be executed on click event
});
$("#table_div").append(code);
}
});
I did not test the code but I think it should work.
Assuming you can't just set up an event-binding function and then call it from the main script (the JavaScript you need can't be guessed ahead of time, for example) then one really easy way is just to append the JavaScript to the bottom of the returned HTML content within script tags. When it's appended along with the HTML, the script should simply execute, with no eval() required.
I can't swear that this would work in old browsers, but it's a trick I've used a couple of times, and I've had no problems with it in Firefox, Chrome, or any of the later IE versions.
I think I see what you're asking here, from my understanding you want to send the new "page" asynchorously, and render the new javascript and html. It looks like you already got your request/response down, so i'm not gonna go and talk about sending JSON objects, and the whole "how-to" of sending html and javascript because it looks like you got that part. To do what you want and to dynamically add your javascript in, this stackoverflow question looks like it has what you need
Is there a way to create a function from a string with javascript?
So pertaining to your example, here is how it would look when you recieve the JSON string from your python script:
$("body").on("click", "#open_table", function() {
$.getJSON('/get_table', function(response){
$("#table_div").append(response.html);
/* Create function from string */
var newFunction = Function(response.javascript['param_1'], response.javascript['param_2'], response.javascript['function']);
/* Execute our new function to test it */
newFunction();
}
});
*Your actual function contents would be the string: response.javascript['function']
*Your parameter names if any would be in separate strings ex: response.javascript['param_1']
That is almost a direct copy of the "String to function" code that you can see in the linked question, just replaced it with your relevant code. This code is also assuming that your object is sent with the response.javascript object containing an array with your actual function content and parameter names. I'm sure you could change the actual name of the var too, or maybe put it in an associative array or something that you can keep track of and rename. All just suggestions, but hopefully this works for you, and helps you with your problem.
I am also doing similar work in my project where I had to load partial html using ajax calls and then this partial HTML has elements which requires events to be attached. So my solution is to create a common method to make ajax calls and keep a js method name to be executed post ajax call in html response itself. For example my server returns below html
<input type="hidden" data-act="onPartialLoad" value="createTableEvents" />
<div>.........rest of html response.....<div>
Now in common method, look for input[type='hidden'][data-act='onPartialLoad'] and for each run the method name provided in value attribute (value="createTableEvents")
Dont Use Eval() method as it is not recommended due to security
issues. Check here.
you can run js method using window["method name"]...so here is a part of code that I use.
$.ajax(options).done(function (data) {
var $target = $("#table_div");
$target.fadeOut(function () {
$target.html(data);
$target.fadeIn(function () {
try {
$('input[data-act="onPartialLoad"]', $target).each(function () {
try {
//you can pass parameters in json format from server to be passed into your js method
var params = $(this).attr('params');
if (params == undefined) {
window[$(this).val()]();
}
else {
window[$(this).val()]($.parseJSON(htmlutil.htmlDecode(params)));
}
} catch (e) {
if (console && console.log) {
console.log(e.stack);
console.log($(this).val());
}
}
});
}
catch (e) {
console.log(e.stack);
}
});
});
});
use jQuery.getScript() (as suggested by Kalimah Apps) to load the required js files first.

Running a service and calculating modal dialog content at once

There is a modal dialog displaying mantle.ledger.transaction.AcctgTransEntry of the selected invoice. A button in the dialog calls a service which posts a GL transaction:
function postTransactionToGl() {
var invoiceId = $("input[id='showGlTransactions_Header_invoiceId_id']").val();
$.ajax(
{
type:"POST",
url:"${sri.buildUrl('postInvoiceToGl').url}",
data:
{
moquiSessionToken: "${(ec.getWeb().sessionToken)!}",
invoiceId: invoiceId
},
dataType:"json"
}
);
};
Then there is a JS function that displays the content of a table in the dialog. It calls a service which returns JSON data with entries included. I would like to fire both functions one after another, first post the transactions, then redraw the table. How shall I do that? Is there a way I can run the service, wait for the transaction to commit and then run the refresh?
This is more of a jQuery question than a Moqui question. The answer is simple: use the 'success' option in jQuery.ajax() to specify a function to call a method to do something. See:
http://api.jquery.com/jquery.ajax/
What you are describing is something that is much easier with an MVVM or MVC tool that runs in the browser. There are many of these out there and currently there is a proof of concept effort to use Vue JS in Moqui. With data binding the callback from the AJAX request would be easy, just update the data in the model and the view will automatically be updated. See the 'vuejs' branch in the moqui-framework and moqui-runtime repositories.

Adding a function to jqGrid to add local JSON

I"m trying to create an additional function for jqGrid to simplify adding JSON data to a grid that uses local data. The following attempt works except for one line, which causes it to fail.
$.fn.myrows = function(data) {
$(this).clearGridData();
$(this).jqGrid("setGridParam", {datatype: "json", loadonce: true});
$("#" + (this).selector)[0].addJSONData(data); // PROBLEMATIC LINE
$(this).jqGrid("setGridParam", {datatype: "local", loadonce: true});
};
This function is then called as $("#myGrid").myrows(jsonDataObject);.
Note that these lines work when they are not inside this function.
Any ideas? Thanks!
In the answer on your previous question I tried to explain how to extend jqGrid to support new method. To tell the truth, I don't see what real advantage you will have from the jqGrid extending. Why not just define your function as
var myrows = function(grid,data) {
// function body
};
and use it in the way:
myrows($("#myGrid"),jsonDataObject);
Much more important thing in my opinion is the implementation of what you need. Your current code have many disadvantages. If the grid has datatype: "local" then the local data paging can be used. The method addJSONData add all the data in the grid, so the page size can be broken.
If you have datatype: "local" and want to fill it with the data then the most effective way will be to set data parameter of the grid with respect of setGridParam and then just call $("#myGrid").trigger('reloadGrid',[{page:1}]) (see here).
Alternative you can use many other existing methods like addRowData which allows to add many rows of data at one method call.
If you get the JSON data from the server and thy to fill the grid with addJSONData method it will be really bad way. The versions of jqGrid starting with the version 3.5 has rich ways to customize the ajax request used. So it is strictly recommended that you don't use addJSONData in the case. See here for details.
You have a typo, do this on the line:
$("#" + $(this).selector)[0].addJSONData(data); // PROBLEMATIC LINE
The $ was missing before this

How does alfresco's javascript( not webscript) mechanism

When I play with alfresco share, I found it is difficult to track the UI and javascript. you can only see some class name in the HTML tags, But you are difficult to know how are they constructed, And When, where and how can these scattered HTML code can render such a fancy page.
Can someone help me ? Please offer several example and explain how they work!
Thanks in advance!
Here is some example that will hopefully help you (it's also available on Wiki). Most of the magic happens in JavaScript (although the layout is set in html partly too).
Let's say you want to build a dashlet. You have several files in the layout like this:
Server side components here:
$TOMCAT_HOME/share/WEB-INF/classes/alfresco/site-webscripts/org/alfresco/components/dashlets/...
and client-side scripts are in
$TOMCAT_HOME/share/components/dashlets...
So - in the server side, there is a dashlet.get.desc.xml - file that defines the URL and describes the webscript/dashlet.
There is also a dashlet.get.head.ftl file - this is where you can put a <script src="..."> tags and these will be included in the <head> component of the complete page.
And finally there is a dashlet.get.html.ftl file that has the <script type="text/javascript"> tag which usually initializes your JS, usually like new Alfresco.MyDashlet().setOptions({...});
Now, there's the client side. You have, like I said, a client-side script in /share/components/dashlets/my-dashlet.js (or my-dashlet-min.js). That script usually contains a self-executing anonymous function that defines your Alfresco.MyDashlet object, something like this:
(function()
{
Alfresco.MyDashlet = function(htmlid) {
// usually extending Alfresco.component.Base or something.
// here, you also often declare array of YUI components you'll need,
// like button, datatable etc
Alfresco.MyDashlet.superclass.constructor.call(...);
// and some extra init code, like binding a custom event from another component
YAHOO.Bubbling.on('someEvent', this.someMethod, this);
}
// then in the end, there is the extending of Alfresco.component.Base
// which has basic Alfresco methods, like setOptions(), msg() etc
// and adding new params and scripts to it.
YAHOO.extend(Alfresco.MyDashlet, Alfresco.component.Base,
// extending object holding variables and methods of the new class,
// setting defaults etc
{
options: {
siteId: null,
someotherParam: false
},
// you can override onComponentsLoaded method here, which fires when YUI components you requested are loaded
// you get the htmlid as parameter. this is usefull, because you
// can also use ${args.htmlid} in the *html.ftl file to name the
// html elements, like <input id="${args.htmlid}-my-input"> and
// bind buttons to it,
// like this.myButton =
// so finally your method:
onComponentsLoaded: function MyDaslet_onComponentsLoaded(id) {
// you can, for example, render a YUI button here.
this.myButton = Alfresco.util.createYUIButton(this, "my-input", this.onButtonClick, extraParamsObj, "extra-string");
// find more about button by opening /share/js/alfresco.js and look for createYUIButton()
},
// finally, there is a "onReady" method that is called when your dashlet is fully loaded, here you can bind additional stuff.
onReady: function MyDashlet_onReady(id) {
// do stuff here, like load some Ajax resource:
Alfresco.util.Ajax.request({
url: 'url-to-call',
method: 'get', // can be post, put, delete
successCallback: { // success handler
fn: this.successHandler, // some method that will be called on success
scope: this,
obj: { myCustomParam: true}
},
successMessage: "Success message",
failureCallback: {
fn: this.failureHandler // like retrying
}
});
}
// after this there are your custom methods and stuff
// like the success and failure handlers and methods
// you bound events to with Bubbling library
myMethod: function (params) {
// code here
},
successHandler: function MyDAshlet_successHandler(response) {
// here is the object you got back from the ajax call you called
Alfresco.logger.debug(response);
}
}); // end of YAHOO.extend
}
So now you have it. If you go through the alfresco.js file, you'll find out about stuff you can use, like Alfresco.util.Ajax, createYUIButton, createYUIPanel, createYUIeverythingElse etc. You can also learn a lot by trying to play with, say, my-sites or my-tasks dashlets, they're not that complicated.
And Alfresco will put your html.ftl part in the page body, your .head.ftl part in the page head and the end user loads a page which:
loads the html part
loads the javascript and executes it
javascript then takes over, loading other components and doing stuff
Try to get that, and you'll be able to get the other more complicated stuff. (maybe :))
You should try firebug for stepping through your client side code.
Alfresco includes a bunch of files that are all pulled together on the server side to serve each "page".
I highly recommend Alfresco Developer Guide by Jeff Potts (you can buy it and view it online instantly).
James Raddock
DOOR3 Inc.

Categories