I am trying to use primefaces Linechart zoom feature to retrive portions of data. For instance, say x-axis represents time. If the whole line chart represents data for a week, by zooming in I can get data for say a day or a few hours.
So, I need an actionlistner that fires on zoom event and from which I can retrieve the starting time and endtime of the zoomed portion.
Any clues guyz?
Thanks in advance.
Ok...I guess noboby knows how to...in any case, I found out the answer after a lot of digging and studying...it can be done using javascript...this is how i did it...incase anyone in the future needs it....
<script type="text/javascript" src="#{request.contextPath}/js/jquery.min.js"></script>
<script type="text/javascript" src="#{request.contextPath}/js/jquery.jqplot.min.js"></script>
<script type="text/javascript" src="#{request.contextPath}/js/plugins/jqplot.dateAxisRenderer.min.js"></script>
<script type="text/javascript" src="#{request.contextPath}/js/plugins/jqplot.cursor.min.js"></script>
<script type="text/javascript" src=".#{request.contextPath}/jsplugins/jqplot.highlighter.min.js"></script>
<script type="text/javascript" >
function open(){
$('#mainForm\\:myPlot').bind('jqplotZoom', function(plot){
var minVal = plot.axes.xaxis.min;
var maxVal = plot.axes.xaxis.max;
//perform any action with these values
});
}
</script>
And the primefaces code part -
<p:lineChart id="myPlot"
value="#{myController.getChartForDialog()}"
legendPosition=""
yaxisLabel="Traffic"
xaxisLabel=""
zoom="true"
extender="open"
showMarkers="true"
seriesColors="ff0000"
style="height:200px; width: 100%" />
This linechart lies within the form 'mainForm'..
Note: Maybe some of the js imports can be removed. Didn't check it.
UPDATE
Here is an updated version of the previous code. This code basically zooms into a line chart having a date time axis as the xaxis. In case, the difference between the start and the end time stamp is less than a day, then the tick label is changed to hh:mm else it is shown as yy-MM-dd.
Versions used
Primefaces 5.3
jsf 2.1.11
Wildfly 10
My bean class -
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.DateAxis;
import org.primefaces.model.chart.LineChartModel;
import org.primefaces.model.chart.LineChartSeries;
#ManagedBean
public class ChartView implements Serializable {
private LineChartModel dateModel;
#PostConstruct
public void init() {
createDateModel();
}
public LineChartModel getDateModel() {
return dateModel;
}
private void createDateModel() {
dateModel = new LineChartModel();
LineChartSeries series1 = new LineChartSeries();
series1.setLabel("Series 1");
series1.set("2014-01-01", 51);
series1.set("2014-01-06", 22);
series1.set("2014-01-12", 65);
series1.set("2014-01-18", 74);
series1.set("2014-01-24", 24);
series1.set("2014-01-30", 51);
LineChartSeries series2 = new LineChartSeries();
series2.setLabel("Series 2");
series2.set("2014-01-01", 32);
series2.set("2014-01-06", 73);
series2.set("2014-01-12", 24);
series2.set("2014-01-18", 12);
series2.set("2014-01-24", 74);
series2.set("2014-01-30", 62);
dateModel.addSeries(series1);
dateModel.addSeries(series2);
dateModel.setTitle("Zoom for Details");
dateModel.setZoom(true);
dateModel.getAxis(AxisType.Y).setLabel("Values");
DateAxis axis = new DateAxis("Dates");
axis.setTickAngle(-50);
axis.setMax("2014-02-01");
axis.setTickFormat("%y-%m-%d");
axis.setTickCount(10);
dateModel.getAxes().put(AxisType.X, axis);
dateModel.setExtender("open");
}
}
My xhtml class containing the js code -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h1>PrimeFaces</h1>
<h:form id="mainForm">
<script type="text/javascript">
function open(){
$('#mainForm\\:myPlot').bind('jqplotZoom', function(ev, gridpos, datapos, plot, cursor){
var minVal = plot.axes.xaxis.min;
var maxVal = plot.axes.xaxis.max;
var timeDiff = Math.abs(maxVal - minVal);
var dayDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
console.log(dayDiff);
if(dayDiff == 1){
plot.axes.xaxis.tickOptions.formatString="%H:%M";
plot.replot();
}
console.log(plot.axes.xaxis.tickOptions.formatString);
});
}
</script>
<p:chart type="line" id="myPlot" model="#{chartView.dateModel}" style="height:300px;" widgetVar="chart"/>
</h:form>
</h:body>
</html>
Hope this helps.
Related
I am teaching myself asp .net mvc 3. I read this tutorial: http://www.codeproject.com/Articles/148949/ASP-NET-MVC-3-the-Razor-View-Engine-and-Google-Map and several other such posts. However, I have not been able to get google map running on my application. what am I doing wrong?
View:
#section Scripts_head {
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
}
<script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(40.716948, -74.003563);
var options = { zoom: 14, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP };
var map = new google.maps.Map(document.getElementById("map"), options);
}
$(function () {
initialize();
});
</script>
<div id="map" style="width:80%; height:80%"></div>
I have also tried putting the div over the script tag.
Layout Page:
<head>
...
#RenderSection("Scripts_head", false)
</head>
Controller:
public class MapController : Controller
{
//
// GET: /Map/
public ActionResult Index()
{
return View();
}
}
If you dont have errors, then its probably sizing of your div "map". Here is your code extracted and working in JsFiddle:
http://jsfiddle.net/GNwU8/3/
Give you map div an absolute size. You have:
<div id="map" style="width:80%; height:80%"></div>
...but that is 80% of what?
instead try:
<div id="map" style="width:400px; height:300px"></div>
I'm trying to figure out if it is possible to append to a section. Here is my structure:
_Layout.cshtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link href="#Url.Content("~/Content/style.css")" rel="stylesheet" type="text/css" />
#RenderSection("Css", false)
<script type="text/javascript" src="#Url.Content("~/Content/scripts/head.load.min.js")"></script>
</head>
<body class="bg_g">
#RenderBody()
<script type="text/javascript">
#RenderSection("Javascript", false)
</script>
</body>
</html>
Logon.cshtml
#{
Layout = "~/Views/Shared/_DMZ.cshtml";
ViewBag.Title = "Logon";
}
#section Javascript += {
// JAVASCRIPT CODE;
}
<div>
Stuff
#{ Html.RenderAction("Register", "Account"); }
#{ Html.RenderAction("Register2", "Account"); }
</div>
Register.cshtml
#{
Layout = null;
}
#section Javascript += {
// More javascript code
}
<div>
Register stuff
</div>
Register2.cshtml
#{
Layout = null;
}
#section Javascript += {
// Even More javascript code
}
<div>
Register stuff part 2
</div>
Hopefully that explains what I'm really trying to do. I would also like to do the same thing with my css section. It would be even better if I could also get it to render the Javascript like this:
head.js(
"#Url.Content("~/Content/scripts/jquery-1.6.2.min.js")",
"#Url.Content("~/Content/scripts/jquery.tools.min.js")",
"#Url.Content("~/Content/lib/jquery-validation/jquery.validate.js")",
// Loop through all javascript files included from the sub views and add them just like above
function () {
loginTabs.init();
// Loop through all javascript functions that have been added to the InitFunctions section?
}
)
Maybe sections aren't the correct solution to this problem, but I know that there has to be a way to accomplish something like this. Any Ideas?
A bit of a late entry - but hopefully still useful to someone out there:
I don't know if there is a native method to achieve it but i have been using this for some time now and it's really helpful:
public static IHtmlString Resource( this HtmlHelper HtmlHelper, Func<object, HelperResult> Template, string Type )
{
if( HtmlHelper.ViewContext.HttpContext.Items[Type] != null ) ( (List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[Type] ).Add( Template );
else HtmlHelper.ViewContext.HttpContext.Items[Type] = new List<Func<object, HelperResult>> { Template };
return new HtmlString( String.Empty );
}
public static IHtmlString RenderResources( this HtmlHelper HtmlHelper, string Type )
{
if( HtmlHelper.ViewContext.HttpContext.Items[Type] == null ) return new HtmlString( String.Empty );
var Resources = (List<Func<object, HelperResult>>)HtmlHelper.ViewContext.HttpContext.Items[Type];
foreach( var Resource in Resources.Where( Resource => Resource != null ) )
{
HtmlHelper.ViewContext.Writer.Write( Resource( null ) );
}
return new HtmlString( String.Empty );
}
The usage is:
//This is how you save it
#Html.Resource(#<style>.test{color: #4e4e4e}</style>, "css")
//This is how you read it
#Html.RenderResources("css")
is there a way to have DatePicker allow user to only choose Sunday/Saturday from the popup dates since week starts from Sunday & ends on a Saturday?
I have 2 DatePickers serving as a range (from & to) and the validation is to allow the user to only select a Sunday in the from box and Saturday in the to box.
Any ideas?
Maybe you can add a jquery event handler for all the links that are week-days (the weekend days have a weekend class on the td) and prevent the default behavior, so whenever you click on them don't do anything. Also you may want to change the style of the weekday values so the user don't get annoyed for clicking and not getting the desired efect
in aspx add the below code
<%# Page Language="C#" AutoEventWireup="true" CodeFile="DefaultCS.aspx.cs" Inherits="DefaultCS" %>
<%# Register TagPrefix="radcln" Namespace="Telerik.WebControls" Assembly="RadCalendar.Net2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<script type="text/javascript">
function OnDayRender(calendarInstance, args)
{
var jsDate = new Date(args.Date[0], args.Date[1] - 1, args.Date[2]);
if (jsDate.getDay() != 0)//(jsDate.getDay()!=6) for Saturday
{
var otherMonthCssClass = "otherMonth_" + calendarInstance.Skin;
args.Cell.className = otherMonthCssClass;
args.Cell.innerHTML = "<span>" + args.Date[2] + "</span>";
args.Cell.DayId = "";
}
}
</script>
<radcln:RadDatePicker ID="RadDatePicker1" runat="server">
<Calendar OnDayRender="Calendar_OnDayRender">
<ClientEvents OnDayRender="OnDayRender" />
</Calendar>
</radcln:RadDatePicker>
</div>
</form>
and in cs file
using System;
using System.Web.UI.WebControls;
using Telerik.WebControls;
using Telerik.WebControls.Base.Calendar.Enumerations;
public partial class DefaultCS : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
RadDatePicker1.Calendar.SpecialDays.Clear();
}
}
protected void Calendar_OnDayRender(object sender, Telerik.WebControls.Base.Calendar.Events.DayRenderEventArgs e)
{
if (e.Day.Date.DayOfWeek != DayOfWeek.Sunday) //(e.Day.Date.DayOfWeek != DayOfWeek.Saturday) for Saturday
{
string calendarSkin = RadDatePicker1.Calendar.Skin != "" ? RadDatePicker1.Calendar.Skin : "Default";
string otherMonthCssClass = String.Format("otherMonth_{0}", calendarSkin);
e.Cell.Text = "";
e.Cell.CssClass = otherMonthCssClass; //set new CssClass for the disabled calendar day cells (e.g. look like other month days here)
Label label = new Label();
label.Text = e.Day.Date.Day.ToString();
e.Cell.Controls.Add(label);
RadCalendarDay calendarDay = new RadCalendarDay();
calendarDay.Date = e.Day.Date;
calendarDay.IsSelectable = false;
calendarDay.ItemStyle.CssClass = otherMonthCssClass;
RadDatePicker1.Calendar.SpecialDays.Add(calendarDay);
}
}
}
Consider the following code (it is based on a default EMPTY MVC3 project created in visual web developer express 2010sp1):
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
Index method of HomeController:
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
alert(result);
});
return false;
//$('#main').load(this.href);
//return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } );
The problem is that in IE8 when the myLink link is clicked, it doesn't update the main div with only the partial html from Index.cshtml but the complete html including the layout. Ofcourse it works fine in FF, I mean why shouldn't it right? It seems Request.IsAjaxRequest() always evaluates to false in IE8. I understand that it is a result of a header X-Requested-With not being attached to a request in IE8. I don't have a lot of experience with web development -- is this a common issue and what is the (best) way to solve this?
UPDATE:
Yesterday I got it working normally in IE8, but when I tried it again this morning, the same problem was back. Now I don't think it has anything to do with the settings in IE8 anymore as I restored the settings to the default values. I tried examining the request with the fiddler tool. In order for me to be able to capture the traffic from localhost with fiddler, I added a period to the address: http://localhost.:3157/. So now the error occurs only when I use http://localhost.:3157/ (with period) and it works normally when I use http://localhost:3157/ (without period). I additionally tested the behavior in Chrome, Opera and Safari -- the ajax link works normally in these browsers. Note that I can get it working normally in IE8 when I attach a query parameter to the ajax link like so:
#Html.ActionLink("Index", "Index", new { controller = "Home", param = "param" }, new { id = "myLink" } )
I don't really want to do this. I'm running low on ideas here. I'm probably missing something that is blatantly obvious to a seasoned web developer =] Anybody recognize these symptoms?
You probably want to use the .live() method instead of .click():
$('#myLink').live('click', function () {
...
return false;
});
because you are replacing the DOM in the AJAX callback (the #main) which contains the link so you are killing the event handler you have assigned.
Also you have a typo in the jquery script inclusion in the <head>. You are missing a closing > after type="text/javascript":
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
So here's a complete working example:
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
});
return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } )
add
jQuery.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
}
});
to make sure the correct header is attached.
In a certain page of our JSF application, the user sees a table listing many objects, which we will call "jobs". Let's say each job has a priority, which is nothing but a number, and in this screen the user is able to edit the priorities of the jobs.
However, two jobs can't have the same priority number. For this reason, I'm finding it hard to build an appropriate UI to deal with setting the priorities.
We tried a simple editbox in the beginning, but it soon became clear that it sucked: if the user wanted to lower the priority of a job from 100 to 50, he would have to manually "make room for that job" by adding 1 to jobs 50 to 99.
Now I'm thinking about a table in which the user could drag & drop the rows to visually adjust priority, without ever having to fiddle with priority numbers (in fact never seeing them), but I can't find such component. Does anybody know of such component or have any better UI suggestion?
I don't think you will find a component that will change the priority numbering for you. Instead you should invoke a re-ordering routine that would update the priority numbers accordingly after changing the priority.
Regarding drag-and-drop, I'll suggest that you look at RichFaces or ICEFaces. RichFaces got some very neat functionality for implementing the sort of thing you are talking about. I'll recommend that you have a look at the RichFaces demo page and try out the drag-drop support components. The RichFaces component set also got an Ordering List (under Rich Selects), but it doesn't seem to allow for changing the ordering by entering a number, rather it is done using up and down buttons.
How about take your current idea and let the computer do the job of making room?
If the user enters 50, display a warning that that job exists, ask if they want the new job inserted before or after the current number 50 or if they want to cancel the operation entirely. If their choice is to insert the entry, you reorder the other items in code.
Check out the jQuery table drag'n'drop plugin. Then just tie the resulting javascript calls into your back-end using Ajax (eg. the a4j:jsFunction from Richfaces). Get the back-end Bean to handle the shuffling of the subsequent jobs.
This will definitely look and behave better than any out-of-the-box component that you'll currently find in a JSF library.
I thought I'd have a go and see if you could do this with the out-of-the box components and script.aculo.us. It is possible, though there would be a bit of work in getting it to look nice and provide a slick UI.
The demo view:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<jsp:directive.page language="java"
contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" />
<jsp:text>
<![CDATA[ <?xml version="1.0" encoding="ISO-8859-1" ?> ]]>
</jsp:text>
<jsp:text>
<![CDATA[ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ]]>
</jsp:text>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Sortable</title>
<script src="javascripts/prototype.js" type="text/javascript">/**/</script>
<script src="javascripts/scriptaculous.js" type="text/javascript">/**/</script>
</head>
<body>
<f:view>
<h:form>
<h:dataTable id="table1" binding="#{jobPageBean.table}"
value="#{jobBean.jobs}" var="row" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="jobs" />
</f:facet>
<h:outputText value="#{row.text}" />
<h:inputHidden value="#{row.priority}">
<f:convertNumber integerOnly="true" />
</h:inputHidden>
</h:column>
</h:dataTable>
<h:commandButton id="ucb1" binding="#{jobPageBean.updateCommandButton}"
action="#{jobBean.updatePriorities}" value="Save New Priority Order"
disabled="true" />
</h:form>
<h:form>
<h:inputTextarea value="#{jobBean.newJob}" />
<h:commandButton action="#{jobBean.addNewJob}" value="Add Job" />
</h:form>
</f:view>
<script type="text/javascript"> /* <![CDATA[ */
Sortable.create('${jobPageBean.tableClientId}:tbody_element', {tag: 'tr', onChange: sortElements});
function sortElements() {
var table = document.getElementById('${jobPageBean.tableClientId}');
var inputs = table.getElementsByTagName('input');
for(var i=0; i<inputs.length; i++) {
inputs[i].value = i;
}
var updateCommandButton = document.getElementById('${jobPageBean.updateCommandButtonClientId}');
updateCommandButton.disabled = false;
}
/* ]]> */
</script>
</body>
</html>
</jsp:root>
Beans:
public class JobPageBean {
// Declaration:
// <managed-bean>
// <managed-bean-name>jobPageBean</managed-bean-name>
// <managed-bean-class>job.JobPageBean</managed-bean-class>
// <managed-bean-scope>request</managed-bean-scope>
// </managed-bean>
private UIComponent dataTable;
private UIComponent updateCommandButton;
public void setTable(UIComponent dataTable) {
this.dataTable = dataTable;
}
public UIComponent getTable() {
return dataTable;
}
public String getTableClientId() {
FacesContext context = FacesContext
.getCurrentInstance();
return dataTable.getClientId(context);
}
public void setUpdateCommandButton(
UIComponent updateCommandButton) {
this.updateCommandButton = updateCommandButton;
}
public UIComponent getUpdateCommandButton() {
return updateCommandButton;
}
public String getUpdateCommandButtonClientId() {
FacesContext context = FacesContext
.getCurrentInstance();
return updateCommandButton.getClientId(context);
}
}
public class JobBean {
// Declaration:
// <managed-bean>
// <managed-bean-name>jobBean</managed-bean-name>
// <managed-bean-class>job.JobBean</managed-bean-class>
// <managed-bean-scope>session</managed-bean-scope>
// </managed-bean>
private List<Job> jobs;
private DataModel model;
private String newJob;
public DataModel getJobs() {
if (jobs == null) {
jobs = new ArrayList<Job>();
model = new ListDataModel(jobs);
}
return model;
}
public String updatePriorities() {
if (jobs != null) {
Collections.sort(jobs);
}
return null;
}
public String getNewJob() {
return newJob;
}
public void setNewJob(String newJob) {
this.newJob = newJob;
}
public String addNewJob() {
if (newJob == null || newJob.trim().length() == 0) {
return null;
}
Job job = new Job();
job.setText(newJob);
job.setPriority(jobs.size());
jobs.add(job);
newJob = null;
return null;
}
}
public class Job implements Comparable<Job> {
private String text;
private int priority;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public int compareTo(Job other) {
if (other.priority == priority) {
return 0;
}
return other.priority < priority ? 1 : -1;
}
}
You can reorder the rows by dragging them, but you need to submit the form to save the changes - you won't get good AJAX support without a 3rd party framework that adds it (at least, not until JSF 2.0)
I used MyFaces 1.2.3, the dataTable of which renders its tbody element with an id attribute ending in :tbody_element - I don't know if all implementations do this
I haven't bothered with too much in the way of input validation, or looked at using the keyboard for accessibility support, or all those other things required for a professional UI...