I'm new to aem. I'm trying to implement the following example in aem by using sightly. currently im working on aem 6.1.
can you please guide me how can i access current time in sightly.
I'm using dialog boxes to show greeting messages according to current time.
<div data-sly-use.clientlibInclude="${'/libs/granite/sightly/templates/clientlib.html'}"></div>
<output data-sly-call="${clientlibInclude.css # categories='angular-global-category'}" data-sly-unwrap />
<html> `enter code here`
<head>
<title>Greeting Message using JavaScript</title>
</head>
<body>
<section class="intro">
<h1> <label id="lblGreetings"></label></h1></section>
</body>
<script>
var myDate = new Date();
var hrs = myDate.getHours();
var greet;
if (hrs < 12)
greet = 'Good Morning';
else if (hrs >= 12 && hrs <= 17)
greet = 'Good Afternoon';
else if (hrs >= 17 && hrs <= 24)
greet = 'Good Evening';
document.getElementById('lblGreetings').innerHTML =
'' + greet + ' Julio';
</script>
</html>
There's no native objects that contain server date information in sightly. To print a date with sightly you need to have a Model related to it and use it within sightly. You can have a javascript model or a java one.
quick js guide found on the net: http://blogs.adobe.com/experiencedelivers/experience-management/htl-javascript-use-api/
If you'd want to go with Java I'd advise using SlingModels or Slice for modelling.
Seems to me you didn't do much reading on sighlty. Please read the docs first.
Actually you can create a java.util.Date as a model:
<sly data-sly-use.time="java.util.Date">${time.hours}</sly>
But that's just for fun or debugging, and not good style - I think it's much better do move such logic into a model, Java or otherwise. (And this just uses the default timezone...)
Related
I currently have a data-sly-list that populates a JS array like this:
var infoWindowContent = [
<div data-sly-use.ed="Foo"
data-sly-list="${ed.allassets}"
data-sly-unwrap>
['<div class="info_content">' +
'<h3>${item.assettitle # context='unsafe'}</h3> ' +
'<p>${item.assettext # context='unsafe'} </p>' + '</div>'],
</div>
];
I need to add some logic into this array. If the assetFormat property is 'text/html' only then I want to print the <p> tag. If the assetFormat property is image/png then I want to print img tag.
I'm aiming for something like this. Is this possible to achieve?
var infoWindowContent = [
<div data-sly-use.ed="Foo"
data-sly-list="${ed.allassets}"
data-sly-unwrap>
['<div class="info_content">' +
'<h3>${item.assettitle # context='unsafe'}</h3> ' +
if (assetFormat == "image/png")
'<img src="${item.assetImgLink}</img>'
else if (assetFormat == "text/html")
'<p>${item.assettext # context='unsafe'}</p>'
+ '</div>'],
</div>
];
To answer your question quickly, yes you can have a condition (with data-sly-test) in your list as follows:
<div data-sly-list="${ed.allAssets}">
<h3>${item.assettitle # context='html'}</h3>
<img data-sly-test="${item.assetFormat == 'image/png'}" src="${item.assetImgLink}"/>
<p data-sly-test="${item.assetFormat == 'text/html'}">${item. assetText # context='html'}"</p>
</div>
But looking at what you're attempting to do, basically rendering that on the client-side rather than on the server, let me get a step back to find a better solution than using Sightly to generate JS code.
A few rules of thumb for writing good Sightly templates:
Try not to mix HTML, JS and CSS in the template: Sightly is on
purpose limited to HTML and therefore very poor to output JS or CSS.
The logic for generating a JS object should therefore be done in the
Use-API, by using some convenience APIs that are made fore that, like
JSONWriter.
Also avoid as much as possible any #context='unsafe', unless you filter that string somehow yourself. Each string that is not
escaped or filtered could be used in an XSS attack. This
is the case even if only AEM authors could have entered that string,
because they can be victim of an attack too. To be secure, a system
shouldn't hope for none of their users to get hacked. If you want to allow some HTML, use #context='html' instead.
A good way to pass information to JS is usually to use a data attribute.
<div class="info-window"
data-sly-use.foo="Foo"
data-content="${foo.jsonContent}"></div>
For the markup that was in your JS, I'd rather move that to the client-side JS, so that the corresponding Foo.java logic only builds the JSON content, without any markup inside.
package apps.MYSITE.components.MYCOMPONENT;
import com.adobe.cq.sightly.WCMUsePojo;
import org.apache.sling.commons.json.io.JSONStringer;
import com.adobe.granite.xss.XSSAPI;
public class Foo extends WCMUsePojo {
private JSONStringer content;
#Override
public void activate() throws Exception {
XSSAPI xssAPI = getSlingScriptHelper().getService(XSSAPI.class);
content = new JSONStringer();
content.array();
// Your code here to iterate over all assets
for (int i = 1; i <= 3; i++) {
content
.object()
.key("title")
// Your code here to get the title - notice the filterHTML that protects from harmful HTML
.value(xssAPI.filterHTML("title <span>" + i + "</span>"));
// Your code here to detect the media type
if ("text/html".equals("image/png")) {
content
.key("img")
// Your code here to get the asset URL - notice the getValidHref that protects from harmful URLs
.value(xssAPI.getValidHref("/content/dam/geometrixx/icons/diamond.png?i=" + i));
} else {
content
.key("text")
// Your code here to get the text - notice the filterHTML that protects from harmful HTML
.value(xssAPI.filterHTML("text <span>" + i + "</span>"));
}
content.endObject();
}
content.endArray();
}
public String getJsonContent() {
return content.toString();
}
}
A client-side JS located in a corresponding client library would then pick-up the data attribute and write the corresponding markup. Obviously, avoid inlining that JS into the HTML, or we'd be mixing again things that should be kept separated.
jQuery(function($) {
$('.info-window').each(function () {
var infoWindow = $(this);
var infoWindowHtml = '';
$.each(infoWindow.data('content'), function(i, content) {
infoWindowHtml += '<div class="info_content">';
infoWindowHtml += '<h3>' + content.title + '</h3>';
if (content.img) {
infoWindowHtml += '<img alt="' + content.img + '">';
}
if (content.text) {
infoWindowHtml += '<p>' + content.title + '</p>';
}
infoWindowHtml += '</div>';
});
infoWindow.html(infoWindowHtml);
});
});
That way, we moved the full logic of that info window to the client-side, and if it became more complex, we could use some client-side template system, like Handlebars. The server Java code needs to know nothing of the markup and simply outputs the required JSON data, and the Sightly template takes care of outputting the server-side rendered markup only.
Looking the at the example here, I would put this logic inside a JS USe-api to populate this Array.
I'm trying to set up a simple select dropdown form with Flask. Based on the option chosen, I grab different data from my database, and display it back into a div on my html template. But I can't seem to get the Flask request to register any of the select options. When I print request.form or request.args, I always get empty Dicts. It's probably something simple I'm missing but I can't seem to find the problem. I've gotten this to work with several input and button forms, but I can't get it to work right for selects.
Here is a bit of my html template code, with the form and select. I've tried both GET and POST method in the form.
<div class="options" id="options">
<form class="form-horizontal container-fluid" role="form" method="GET" action="exploresn2.html">
<div class="form-group">
<label for="xaxis" class="col-sm-2 control-label">X-axis:</label>
<div class="col-sm-2">
<select name="xaxis" class="form-control" id="xaxis">
<option selected value="mjd" id="mjd">MJD</option>
<option value="seeing" id="seeing">Seeing</option>
<option value="airmass" id="airmass">Airmass</option>
<option value="hourangle" id="hourangle">Hour Angle</option>
</select>
</div>
</div>
</form>
</div>
In Flask, at first, I tried inside my app
import flask
from flask import request, render_template, send_from_directory, current_app
explore_page = flask.Blueprint("explore_page", __name__)
#explore_page.route('/exploresn2.html', methods=['GET','POST'])
def explore():
xaxis = str(request.args.get("xaxis", "any"))
.... [populate new xaxis variable based on request option selected]
exploreDict['xaxis'] = xaxis
return render_template("exploresn2.html", **exploreDict)
or
mjd = valueFromRequest(key='mjd', request=request, default=None)
if mjd:
mjds = [int(exp.platedbExposure.start_time/(24*3600)) for exp in exposures]
xaxis = mjds
exploreDict['xaxis'] = xaxis
to look for and grab a specific values, or in the first case, any value select. The valueFromRequest is function that grabs data from either GET or POST requests.
but this returns nothing, and then I tried just printing the entire request.args (or request.form) and it returns and empty Dict. Everything I try it still returns empty Dicts. So I'm missing some set up somewhere I think but the form looks right to me?
I'm not sure if this is the actual answer to this problem that I was looking for, but here is what I came up with. I couldn't actually get the Flask to accept a GET request into the original explore method defined, so I implemented a new method in Flask to return a JSON object
#explore_page.route('/getdata', methods=['GET','POST'])
def getData(name=None):
name = str(request.args.get("xaxis", "mjd"))
xaxis = 'populate new xaxis data based on value of name'
data = '(x,y) data array filled with values for plotting'
axisrange = range of x,y data for axes for plot
return jsonify(result=data, range=axisrange)
and then I just made a GET request via javascript to that method whenever the select button changes. So in my exploresn2.html template I have (using Flot for plotting)
$("#xaxis").change(function(){
var newname = $("#xaxis :selected").text();
var axes = plot.getAxes();
options = plot.getOptions();
var plotdata = plot.getData();
// make a GET request and return new data
$.getJSON($SCRIPT_ROOT + '/getdata', {'xaxis':$("#xaxis :selected").val()},
function(newdata){
// set new data
for (var i = 0; i < plotdata.length; ++i) {
plotdata[i].data = newdata.result[plotdata[i].label];
}
// set new axes
axes.xaxis.options.panRange = [newdata.range[0]-50,newdata.range[1]+50];
axes.xaxis.options.axisLabel = newname;
axes.xaxis.options.min = newdata.range[0]-1;
axes.xaxis.options.max = newdata.range[1]+1;
axes.yaxis.options.min = newdata.range[2];
axes.yaxis.options.max = newdata.range[3];
// redraw plot
plot.setData(plotdata);
plot.setupGrid();
plot.draw();
});
});
How to get date values in month, year and days in grails datePicker
<g:datePicker id="test" name="test" precision="day"></g:datePicker >
I tried using getDate() but I do not get any value.
Try this approach, first register change handler to each of the 3 selects generated by the datePicker tag, then call the dateWasChanged method and inside that build your date and update your mydate div.
Note: On date Object month is 0 base (index) so you need to deduct 1 unit from the actual select value.
<body>
<g:datePicker id="test" name="test" precision="day"></g:datePicker >
<div id="mydate"></div>
<script type="text/javascript" charset="utf-8">
dateWasChanged()
$( "#test_day" ).change(function() {
dateWasChanged();
});
$( "#test_month" ).change(function() {
dateWasChanged();
});
$( "#test_year" ).change(function() {
dateWasChanged();
});
function dateWasChanged(){
var year = $( "#test_year" ).val();
var month = $( "#test_month" ).val()-1;
var day = $( "#test_day" ).val();
var date = new Date(year,month,day);
$("#mydate").text(date.toString())
}
</script>
</body>
Try something like the following:
Date myDate = params.date('test', 'dd-MM-yyyy')
That will give you a good ol' fashioned java.util.Date object with Groovy extensions that you can use from there. Be sure to set the format (in my case 'dd-MM-yyyy') to whatever date format you are using.
i hav created a jsp page from which i m taking some values and on submit it should pass the parameters to the java class using rest.
< form id="payment" method="post" action="addtogroup">
< ol style="padding: 0;">
< li>< label for="groupId">Group id:< /label>
< input type="text" id="groupId" name="groupId"/>
< br />
< li>< label for="vendorId">Profile Id :< /label>
< input type="text" id="vendorId" name="vendorId"/>
< li>
< input type="submit" value="Submit"/>
< br />
< /ol>
< /form>
and the java code is:
#RequestMapping(value = "/addtogroup/{groupId}/{vendorId}",method = RequestMethod.POST)
public String addtoGroup(#ModelAttribute("groupId") String groupId,#ModelAttribute("vendorId") String profileId){
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
System.out.println("group id is="+groupId);
System.out.println("profileId is="+profileId);
System.out.println("username is="+username);
grpDao.addToGroup(groupId,profileId,username);
return "addtogroup";
}
when i type [http://localhost:8080/biznex/rest/addtogroup/2/13] in the address bar directly the code is executed.
but when i click submit button in the jsp i get page not found error.
plz help me out.
< form id="payment" method="post" action="addtogroup"> This statement means submit the FORM data using POST method to the url "currentpath"/"addtogroup"
However, your RESTFUL Server side component expects the url in the form of /addtogoup/{groupid}/{vendorid} in a GET method
I would suggest you to have a JavaScript method which converts your form fields to the URI path- using jQuery or plain JavaScript
As thewhiterabbit wrote, you have to pass the complete REST url with the groupid and vendorid.
In order to build it you don't need to use JS, it's enough the spring tag library. Here, how it works:
<spring:url value="/addtogoup/${form.groupid}/${form.vendorid}" var="actionURL"/>
<form:form method="POST" action="${actionURL}" modelAttribute="form">
I have a Sharepoint data entry Form for my List (Inspection Table), which has a field called "Date Entered". I want to automatically populate today's date and time when a user clicks on "Add new entry", as I want to use that as audit data.
Now, I wanted to use java script (as after research, this seems the most straight forward way to do so), so I added the following to the NewForm.aspx page:
<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">
<script language="javascript" type="text/javascript">
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
if(dd<10)
{dd='0'+dd;}
if(mm<10)
{mm='0'+mm;}
var formattedToday = mm+'/'+dd+'/'+yyyy;
alert(formattedToday);
document.getElementById('<%= ((TextBox)this.onetIDListForm.FindControl("ff10_1")).ClientID %>').value = formattedToday;
</script>
</asp:Content>
The alert(formattedToday); is just to test if the java script is picked up of course and will be removed in later stage.
Ok.. I get the popup, so the value is calculated correctly and java script works. The problem I have, is putting this value to the "Date Entered" field.
What would be the correct method to call the document.getElementByID?
I have tried multiple variations:
document.getElementById('<%= ((TextBox)this.onetIDListForm.FindControl("ff10_1")).ClientID %>').value = formattedToday;
Or..
document.setElementById("Date Entered").value = formattedToday;
Or..
document.setElementById("ff10_1").value = formattedToday;
Can somebody point me to the correct format, or the way to make this work?
Next to the script above, I think I need the Form field "Date Entered" behavior (enable view) to be set to "False" but that is out of scope at the moment.
Thanks,
Chris
Take a look at this article. It talks about how you can achieve this using jQuery. See sample below and try it out. You will have replace the column name with your corresponding name "Date Entered". This should populate the appropriate textbox for you.
<script type="text/javascript">
$(function() {
$('input[title=DefaultMeFieldNoSpaces]').attr(
{value: 'You are in a twisty maze of passages, all alike.'});
});