I am trying to add multiple-tabs capability to my JSF(facelets)/Spring/ application, something like OpenBravo already has (http://wiki.openbravo.com/w/images/9/9c/WIK_PartsOfScreen.png, but their app is using different technologies - I guess - pure JavaScript for GUI): each document or report can be opened in separate JavaScript tabs.
Bascially it is simple - each document or report is separate JSF region and only one of them is made visible. Tabs are only visual effect.
The problem is communication with JSF backing beans (or Spring beans that sometimes can be employed in this role). E.e. is is simple for one tab interface: one can create the following bean:
class BankDocumentServiceBean {
BankDocument selectedDocument;
Long id;
void setId(Long id) {
if (selectedDocument.id!=id) {
setupBankDocument(id);
}
}
void setupBankDocument(Long id) {...}
BankDocument getBankDocument() {...}
...
}
And BankDocument JSF page can be something like this:
...
<f:metadata> <!-- page is called with parameter id and this code calls setId(...) -->
<f:viewParam name="id" value="#{bankDocumentServiceBean.id}"/>
</f:metadata>
<h:body>
...
<!-- p for Primefaces -->
<p:inputText id="amountTxt"
value="#{bankDocumentServiceBean.selectedDocument.amount}"
required="true" label="amountLbl"/>
<p:message for="amountTxt" />
...
Is this approach generally good?
The main question is - how this single-document approach can be extended to multiple tabes. JSF code can be included in the page dynamically, but the service bean remains the problem. Use of additional parameters in each call can be solution - e.g. BankDocumentServiceBean can contain not single BankDocument but List of BankDocuments and each opearation (e.g. getBankDocument) can have additional identifier for selection the right bean from the collection, i.e., the bean that is relevant for the tab with which the user interacts.
But maybe there is some better approach. E.g. maybe one page can be multiple instances of the old good single-document BankDocumentServiceBean. Maybe there are less coarse scopes (JSF scopes and Spring scopes) that are good for tabs, some kind of conversation scope?
Each tab is sitting in its own general panel (div) with its distinct id. Maybe JSF/Spring application can detect that request is coming from distinct panel/div and select instance of BankDocumentServiceBean accordingly?
I guess - solution with List and parameters will work, but maybe there is better architecture for this? Thanks!
Not a complete a solution but a good starting point for handling multiple browser tabs in a jsf web application:
A very good read in dealing with multiple tabs: http://myfaces.apache.org/orchestra/myfaces-orchestra-core/multiwindow.html
I also recommend Apache Codi scopes for this.
Related
In JSF, what would be the "right" and "clean" way to integrate JavaScript i.e. into a composite-compenent? I am a fan of Unobtrusive JavaScript, and separating HTML from JS from CSS. What would be a good way to have as little quirks as possible? This is what I like the best so far:
<composite:interface>
// ...
</composite:interface>
<composite:implementation>
// ...
<script> initSomething('#{cc.clientId}'); </script>
</composite:implementation>
What I don't like is, to use language A to generate language B. Basically the same goes for event handlers and stuff. My favorite would be to attach those handlers via <insert favorite DOM JavaScript library here>. Is this possible? How do you do this kind of integration?
I'd say that what you've there is the best you can get, provided that you're absolutely positive that the HTML element's nature is so unique that you absolutely need to select it by an ID, every time again.
If the HTML representation is not that unique (I can imagine that a Facelets template or include file might contain application-wide unique HTML elements like header, menu, footer, etc, but a composite component which can be reused multiple times in a single view? I can't for life imagine that), then you could also consider using an unique classname and hook initialization on it.
E.g. /resources/composites/yourComposite.xhtml
<cc:implementation>
<h:outputScript library="composites" name="yourComposite.js" target="head" />
<div id="#{cc.clientId}" class="your-composite">
...
</div>
</cc:implementation>
with in the /resources/composites/yourComposite.js (assuming that you're using jQuery)
var $yourComposites = $(".your-composite");
// ...
You can if necessary extract the autogenerated HTML element ID for each of them in a jQuery.each():
$yourComposites.each(function(index, yourComposite) {
var id = yourComposite.id;
// ...
});
I am trying to build a time slot calendar whereby a booking manager can create timeslots from a calendar. I have found some examples below:
Time slot calendar
XRTML Calendar Booking
Was wondering is it possible to have xRTML work with Ruby On Rails. I downloaded the .js file and put this in my assets/javascript folder.
I found that xRTML has its own tags and put the demo code in an index.html.erb. But this did not seem to work.
My index.html.erb file looked like the following:
<xrtml:config debug="false">
<xrtml:connections>
<xrtml:connection appkey="myAppKey" authenticate="false"
authtoken="myDevToken" url="http://developers.realtime.livehtml.net">
<xrtml:channels>
<xrtml:channel name="myChannel" permission="write"/>
</xrtml:channels>
</xrtml:connection>
</xrtml:connections>
</xrtml:config>
<xrtml:calendar channelid="myChannel" dayonly="false"
enddate="2011-12-13" handlerurl="./handler/calendarTest.ashx"
id="calendarXPTO" lang="en" receiveownmessages="true"
startdate="2011-08-13" target="#divcalendar" userid="userxpto">
<xrtml:triggers>
<xrtml:trigger name="myTrigger"/>
</xrtml:triggers>
<xrtml:slots>
<xrtml:slot value="09:00 - 10:00|10:00 - 11:00|11:00 - 12:00|12:00 - 13:00|15:00 - 16:00|16:00 - 17:00|17:00 - 18:00"/>
<xrtml:slot value="09:00 - 18:00" weekday="Sat"/>
<xrtml:slot weekday="Sun"/>
</xrtml:slots>
</xrtml:calendar>
I have also considered using Jquery full calendar to help me achieve what I am trying to do. However this is proving to be more difficult than I thought. Is there anything similar out there that is like what I am trying to do
My initial idea is to have some sort of calendar with times listed vertically and have slots horizontally enabling a user to click a plus sign that will create new slots as it were.
xRTML is designed to work with any platform/framework that sends HTML to the the browser so
there is no limitation about Ruby or Ruby on Rails.
There are four things missing in your code, Djj:
1) your Connection tag still has the values appkey and authtoken set to the defaults that come with the documentation, you need to use the ones provided in the development kit...
<xrtml:connection appkey="myAppKey" authenticate="false" authtoken="myDevToken" url="http://developers.realtime.livehtml.net">
2) you are not including the script into your page (maybe you just didn't paste it into your question, but:)
<script type="text/javascript" src="path/to/xrtml.js"></script>
3) the Calendar tag requires an HTML container where it is going to be rendered. In the tag, you see target="#divcalendar", that is a Sizzle selector for a div where the calendar's html will be rendered, so you must include, somewhere:
<div id="divcalendar"></div>
4) the handler for the persistence... this is where things get serious. The Calendar tag, requires a server side handler and a database to deal with the records. so, you have to implement in ruby, a handler for the ajax calls made by the calendar (you can find the documentation for it in http://docs.xrtml.org/markup/calendar.html, in the '3.2 Persistence Data' section). So, when defining the tag:
<xrtml:calendar ... handlerurl="path/to/yourhandler" ...></xrtml:calendar>
I'm trying to figure out what the best practice is for using jQuery in an MVC app. Specifically, I would like to know what I should do so that I don't clutter all my views with individual document.ready statements.
As an example:
I have the following Views:
/Views/Shared/_Layout.cshtml
/Views/Home/Index.cshtml
/Views/Home/_Dialog.cshtml
/Views/Home/_AnotherDialog.cshtml
I have a controller action that will render the Home/Index View, which uses the Layout and renders two partial views (or editor templates, display templates, etc.). This one controller action has rendered 4 or more views. Each view is using some jquery document.ready code.
Currently, I have the code at the bottom of each view:
// In Index
<script type="text/javascript">
$(function() {
$('#tabs').tabs()
});
</script>
// In _Dialog
<script type="text/javascript">
$(function() {
$('#some-dialog').dialog( ... );
});
</script>
I know this isn't a very good practice because it is already getting unmanageable in my small project. What are some good practices to follow when I have tons of pages that all need some jQuery / javascript initialization code separated across dozens of views?
You could do something along the lines of what Telerik do with their javascript registrar. Basically, make this registrar available in your view model. At the simplest level, all it has to do is keep track of strings added to it:
public class JavascriptRegistrar
{
private StringBuilder jsBuilder_ = new StringBuilder();
public Add(string js)
{
builder.Append(js).Append('\n');
}
public string ToString()
{
return "<script type=\"text/javascript\">" + jsBuilder_.ToString() + "\n</script>";
}
}
Your partial views will then add to this when rendering:
<h1>In my view!</h1>
#Model.Registrar.Add("$function() { /* ... */ }")
Finally, at the bottom of your main view, when you're done:
#Model.Registrar.ToString()
Which will write out all the javascript it has collected during rendering.
If the initialisation is specific to a view and you know it definitely won't be used outside that view, for example some page specific behaviour, then just leave it in the view!
There is nothing wrong with having script tags in all your views, as long as you aren't replicating js between views. I think people tend to misunderstand 'separation of concerns' in this case and think that simply means 'keep different languages away from each other at all costs'...that is wrong, clearly if some page initialisation logic/behaviour is specific to a page, then the html and js intrinsically 'concern' each other, therefore moving the js into a separate file is not really 'good practice', if anything it makes your code more difficult to understand.
I personally like to open up a View, and be able to see all the js and css that is specific to that page as soon as I open it, makes it nice and readable. However, obviously if code needs to be shared then you need to bust it out your view and get in your scripts folder whwere it can be referenced by anything!
EDIT
In your example above I see in your Index view you initialise your tabs. This is fine as it is, however, if you added tabs somewhere else in the project then it might be better to create your tabs using a .tabs class rather than #tabs id, and then in an external js file initialise all your tabs at once by calling $('.tabs').
I am building app with php and jquery and it has many ajax loads and functionalities. What i would like to know is what is the most widely used and acceptable way of accessing dom elements with jquery and adding events to it using jquery and javascript and if there is any rule of thumb to follow for the following instances.(and how i do them now)
A query generates a list of records and each record has to be edited and deleted.
The generated records look like this
Record1
Record1
Record2
Record2
Record3
Record3
and my jquery code handle them would be
$(".edit").click(function() {
var currentElementId = $(this).attr("id").replace("edit-id-","");
$("#ajaxdiv").load("ajaxpage.php","editid="+currentElementId);
});
is this type of stuff ok? i mean is there any other way to do stuff like this especially when this gets more complicated like have to add 3 more identifiers to id and then exploding them and finding out each of the identifiers separately. Any guidelines here to follow.?
If you simply need to have something that can be cleaner, maybe you can consider bind the record into one
meaningful div, and use .live() to bind the event handlers
i.e.,
<div data-rec-id = '300'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
<div data-rec-id = '301'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
$('.edit').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
$("#ajaxdiv").load("ajaxpage.php","editid="+id);
});
or even generic:
$('.link').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
var action = $(this).attr('data-act');
$("#ajaxdiv").load("ajaxpage.php","id="+id+"&act="+action);
});
Please don't use something like:
<a href="javascript:;" ...
or I would suggest you use some robust framework. e.g., http://documentcloud.github.com/backbone/
I think the way you've done it is acceptable. You're mostly concerned about manually doing string processing to fetch the element ID? That is a little messy but not too bad.
If you don't want to do it that way, you might consider attaching a separate event handler to each a element when you create them, and have that event handler know the ID as a closure variable. But that will consume more memory, so it will depend on how many of those links you have.
I've found using using the web server to server up static web pages with the only dynamic content being json passed back and forth, is the best overall approach. We post JSON, and get JSON back from the server. This is used to design the page. This makes the web server become a data communication rather than heavy lifting the page constructing. This also add the ability for an API structure you can give out to ppl and they can write apps for it. For example, the web site and the mobile application use the same API interface.
As it's recommended, Javascript must be kept in a physically separate file (to be unobtrusive). So how do I access a particular element in particular page? should I detect those elements by id? that would mean 2 elements can't have the same id even if they are not located in the same page.
Well, for instance, using the Html helpers methods generates element's name + id from the model's properties. If I use the same model in several pages, many elements will have the same id. How can I target them in different pages. By the way, CSS work the same way.
EDIT
Let's say I've this
<% = Html.TextBoxFor(x => x.FirstName)%>
It will generates
<input type = "Text" name = "FirstName" id = "FirstName"/>
Let's say I've this textbox in 2 differen pages. If want, for instance, to disable the textbox located in page A, how do I do it knowing they are two of them in 2 different pages. How do I discriminate them from my external javascript file?
Thanks for helping
I suggest that for each page the uses the same model, you create a wrapper div
<div class="pageA">
// the model stuff here
<% = Html.TextBoxFor(x => x.FirstName)%>
</div>
<div class="pageB">
// the model stuff here
<% = Html.TextBoxFor(x => x.FirstName)%>
</div>
and then use Jquery selectors to get the correct element $(".pageA input[name='FirstName']") (not sure if this syntax is correct).
You cannot have multiple elements on the page with the same id. That isn't valid HTML.
So when you use the same HTML helper multiple times, you need to pass different names:
<%: Html.TextBox("Foo", Model.Foo) %>
<%: Html.TextBox("Bar", Model.Bar) %>
Correct me if i'm wrong, but are you saying, you have some elements with the same id, on multiple pages, that you want to attach different behaviour to? If so then this could help you out. if not, then what Craig said.
You can use more specific selectors, or give your selectors context
have a look at the documentations here: http://api.jquery.com/jQuery/
under this header:
jQuery( selector, [ context ] )
it explains a bit about selects and context. you should be able to use this and some creative page building to target the right element with your jQuery.
So you have two files, each with a text field with the id "FirstName". When you're script runs on Page A you want to disable the field, but not when your script runs on Page B.
Is the structure of the two pages identical? I suspect not if you're handling these fields differently. Use the context to your advantage. Like if the one on Page A is in a div with id "thisDiv" and the other is in a div with id "thatDiv" you could document.getElementById('thisDiv'). If you get an element then disable the field, if not do nothing.
If you want a more specific answer you're going to have to give us more context.
Well JavaScript may be kept in a separate file or not, but it is definitely included as part of the HTML send to the browser for a particular page. I Hope I've understood your question, but, generally if you have you JavaScript code in a file, lets say utils.js then in your html generated should include (probably within the <head> tag):
<script type="text/javascript" src="/path/to/utils.js"></script>
The script get included in the page, and when the browser encounters this, it loads and then runs the script, for that page. Therefore, it is not important what the ids for elements on different pages are.
Does that make sense, or have I completely misunderstood your question?
Update:
Ok, so based on your comments, I think I understand. You have
//Page 1
//When loaded, this input should flash blue via javascript for example
<input id="firstName" .../>
And
//Page 2
//When loaded, this input has some other fancy effect/behaviour
<input id="firstName" .../>
Well in this case, as far as I see, there are only 2 types of answers. Have two seperate external js files, one per page and this way you can change to your hearts content ...OR... have some sort of hidden field in your page that tells your script what page it is looking at (this seems hacky)
<input type="hidden" value="page1"/> //etc..