I'm using Wicket and I have followed this guide (and also this one) to build a webpage template.
My goal is to have a fixed header and footer and a dynamic <div> inside <body> that change its content when I change page by clicking on some menu links.
So at the end I have done something like this:
HomePage.html
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title wicket:id="title"> Title </title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div wicket:id="menu"></div>
<div wicket:id="homepageContent"></div>
<div id="content" wicket:id="template" class="">
<wicket:child/>
</div>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="js/myjs.js"></script>
</body>
</html>
HomePage.java
public class HomePage extends WebPage {
// Title of the current page
private String pageTitle;
public HomePage() {
// dynamic page title
add(new Label("title", new PropertyModel<>(this, "pageTitle")));
// ...
}
// ...
public String getPageTitle() {
return pageTitle;
}
public final void setPageTitle(String title) {
pageTitle = title;
}
}
Menu.java
public class Menu extends Panel {
public Menu(String id) {
super(id);
add(new BookmarkablePageLink<>("homepageLink", HomePage.class));
add(new BookmarkablePageLink<>("page1Link", Page1.class));
add(new BookmarkablePageLink<>("page2Link", Page2.class));
}
public Menu(String id, IModel<?> model) {
super(id, model);
}
}
Page1.java
public class Page1 extends HomePage {
public Page1() {
setPageTitle("Page1");
// ...
}
}
Page2.java
public class Page2 extends HomePage {
public Page2() {
setPageTitle("Page2");
// ...
}
}
The problem is that everytime I use my Menu to open a page (Page1 or Page2) the browser reloads all resources, I think it's due to Page1 and Page2 that are children of HomePage.
So, for example, one issue I have is that if I want my Menu to keep track of the page I'm currently visiting by setting a active class via javascript, I will have troubles because everytime I visit a page the js files (and all the others) are downloaded again and I loose all the logic I did.
I just would like to change the content of:
<div id="content" wicket:id="template" class="">
</div>
without refreshing all the rest of the page.
Is it possible to do that just by changing the Wicket approach?
Thanks
What you want to do is basically a Single Page Application. In this case page inheritance doesn't work well. You need to turn Page1, Page2, etc... into Panels and use AJAX to place them as page content (in your code wicket:id="template") when user clicks menu items.
You should to use <wicket:extend></wicket:extend> in parent markup. Something like:
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title wicket:id="title"> Title </title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<wicket:extend>
<div wicket:id="menu"></div>
<div wicket:id="homepageContent"></div>
<div id="content" wicket:id="template" class="">
<wicket:child/>
</div>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="js/myjs.js"></script>
</wicket:extend>
<section id="content">
<wicket:child/>
</section>
</body>
</html>
<wicket:child> is used inside the parent’s markup to define where the children pages/panels can “inject” their custom markup extending the markup inherited from the parent component.
Now only the child markup will updating, I'm not completly sure, but looks like only child part updating.
Related
I am trying to automate a page which has various element types. I am able to login and navigate till that page using Protractor,TypeScript,jasmine2 combination
When i try to enter a text in a field, it throws
Message: Failed: element not interactable.
Does it mean that the entire ng-controller or ng-scope is disabled for element interaction for automation?
Please let me know a solution if there is a way to enable the elements in the page on pageLoad ?
import { browser, by, element } from 'protractor';
import { Locator } from 'protractor/built/locators';
import { PageObjects } from '../TestPageObjects/OR';
import { TestData } from '../TestData/TD';
var po= new PageObjects();
var data= new TestData();
describe('Login', function() {
it('Login to Server', function() {
browser.get('http://server01/test/testapp.html');
element(<Locator>by.xpath(po.login_username)).sendKeys(data.username);
element(<Locator>by.xpath(po.login_password)).sendKeys(data.password);
element(<Locator>by.xpath(po.login_loginBtn)).click();
element(<Locator>by.xpath(po.MainMenu_setup)).click();
element(<Locator>by.xpath(po.SETUP_company)).click();
element(<Locator>by.xpath(po.COMPANY_companyDetails)).click();
browser.switchTo().frame(element(by.id('ifmPortalInfrastturcture')).getWebElement());
browser.sleep(10000);
browser.element(<Locator>by.xpath(po.CompanyName)).clear();
browser.element(<Locator>by.xpath(po.CompanyName)).sendKeys('ANN');
});
});
I expected the behavior to be like entering the text but the terminal showed element not interact-able.
PageObject (PO) selector is below:
export class PageObjects
{
public login_username: string ='//*[#id="username"]';
public login_password: string ='//*[#id="password"]';
public login_loginBtn: string ='//*[#id="btnSubmit"]';
public MainMenu_setup: string ='//a[span[text()="Setup"]]';
public SETUP_company: string ='//a[span[text()="Company"]]';
public COMPANY_companyDetails: string ='//a[span[text()="Company Details"]]'
public CompanyName: string = '//label[contains(.,"Company Name")]/following::input[1]';
//a[span[text()="Receipts"]]
//a[span[text()="Control Text"]]
}
HTML Page is below:
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="portalInfrastructure" dir="ltr">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>iProof Axon</title>
<link rel="icon" href="favicon.ico" type="image/ico" />
<style>
#font-face {
font-family: 'FontAwesome';
src: url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.eot?v=4.7.0');
src: url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),
url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),
url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),
url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),
url('iProofCDN/Templates/Default/Styles/LTR/assets/css/Common/icons/fontawesome/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body ng-controller="PortalInfrastructureController as menuList" class="pace-done " ng-init='setPageUrlByPageType("Authenticate", "#pageManager")' id="bdyPageManager">
<div id="pageManager"></div>
<div id="MultiWindowRight" class="noItem " style="display:none">
<img data-imgsrc="/Templates/Default/Styles/LTR/assets/images/RightArrow.png" />
<div class="MultiWindow"></div>
</div>
<script type="text/javascript" src="iProofCDN/Templates/Default/Scripts/JsBundle/Common/ProofConfig.js"></script>
</body>
</html>
<script type="text/javascript">
window.top.ScriptLoader('PageManager', window.document, function () {
//default
});
</script>
with some research one of my colleague found a solution.
The container elements were hidden for access and we unlocked using the following script:
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("document.getElementById('Parks').style.display='block';");
NOTE: a Div named "Parks" was a child inside the xmlns which is again a child of an iFrame.
I am using webstorage to save data.When i get the data through form & save it in a variable (in this case 'one') and try to display in the same page , it does that correctly. But when i import the same '.js' file and try to display it in a different page, it doesn't work. How to use webstorage to retrieve the data in a different page ? Also, i don't want to use query string !
First page:
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="webstorageAPI.js"></script>
<link href="webstorageAPI.css" rel="stylesheet" type="text/css" />
</head>
<body>
<section id="leftbox">
<section id="leftbox">
<form action="seconddisplayfile.html" method="post">
<p>(key) One: <input type="text" id="one" /></p>
<p>(value)Two:<textarea id="two"></textarea></p>
<p><input type="submit" id="button" value="Save" /></p>
</form>
</section>
<section id="rightbox">
Nothing yet !
</section>
</section>
</body>
</html>
Second page:
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script src="webstorageAPI.js"></script>
<link href="webstorageAPI.css" rel="stylesheet" type="text/css" />
</head>
<body>
<section id="wbox">
Nothing yet!
</section>
</body>
</html>
Javascript code:
// JavaScript Document
function doFirst(){
var button = document.getElementById("button");
button.addEventListener('click',save,false);
}
function save(){
var one = document.getElementById("one").value; //but only contents is to be taken not label n all
var two = document.getElementById('two').value;
localStorage.setItem("one",two); //Store in key-value pair. Anytime you use this you use if by addressing the variable ie key name.
//Retriveing data n displaying stored data
display(one); //now u hav stored two so its time to use one
}
function display(one){
var rightbox = document.getElementById('rightbox'); //refer right box
var two= localStorage.getItem("one"); //Get in key-value pair
rightbox.innerHTML= "Name of variable:"+one+"<br/>Value:"+two;
/*----Second page display-----*/
var wbox = document.getElementById("wbox");
wbox.innerHTML= "Name of variable:"+one+"<br/>Value:"+two;*/
}
window.addEventListener('load',doFirst,false);
#charset "utf-8";
/* CSS Document */
#leftbox{
float:left;
padding:20px;
border:3px solid #F20B84;
}
#rightbox{
float:left;
width:250px;
margin-left:20px;
padding:20px;
border:3px solid #8E1783;
}
Your second page doen't contain any element with id rightbox.so
var rightbox = document.getElementById('rightbox');
will return null.and when try to set innerHTML property of rightbox,js will throw
Uncaught TypeError: Cannot read property 'innerHTML' of null
so change your display to
function display(one){
var rightbox = document.getElementById('rightbox'); //refer right box
var two= localStorage.getItem("one"); //Get in key-value pair
if(rightbox)
rightbox.innerHTML= "Name of variable:"+one+"<br/>Value:"+two;
/*----Second page display-----*/
var wbox = document.getElementById("wbox");
wbox.innerHTML= "Name of variable:"+one+"<br/>Value:"+two;*/
}
You have to call display in second page .
I tried making this tutorial work by just copying it to the letter.
It didn't have the folders entirely right so I just put them in the right ones.
In my: /webapp/VAADIN/themes/mytheme/layouts folder I have the my-layout.html file. Which looks like this:
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div location="top" id="top"></div>
<div>
<span location="bottom" id="bottom"></span>
<span location="left" id="left"></span>
</div>
</body>
</html>
In my Java file it looks like this:
#Override
protected void init(VaadinRequest request) {
CustomLayout layout = new CustomLayout("my-layout");
MenuBar menuBar = new MenuBar();
layout.addComponent(menuBar, "top");
layout.addComponent(new Button("Does Nothing"), "bottom");
VerticalLayout vLayout = new VerticalLayout();
vLayout.addComponent(new InlineDateField());
vLayout.addComponent(new TextField("", "Nothing to put in here"));
vLayout.setSpacing(true);
vLayout.setMargin(true);
vLayout.setVisible(true);
layout.addComponent(vLayout, "left");
layout.setVisible(true);
}
When I run this on the Jetty Server through netbeans, the site doesn't show any of the elements.
you have to set your layout as content in the UI:
setContent(layout)
I have a JSP page :
employee5_searchByName.jsp
<%#page import="java.util.Iterator"%>
<%#page import="java.util.List"%>
<!-- EMPLOYEE wants to search items by their name -->
<!DOCTYPE html>
<html>
<head>
<title>Employee - Search for items by name</title>
<link rel="stylesheet"
href="./css/styles.css"
type="text/css"/>
<link rel="stylesheet" type="text/css" href="css/jquery.autocomplete.css" />
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("jquery", "1");
</script>
<script src="js/jquery.autocomplete.js"></script>
<style>
input
{
font-size: 120%;
}
</style>
</head>
<body>
<h1>Employee - Search for items by name</h1>
<h1>
Search for items by name
</h1>
<fieldset>
<legend>Please enter the item's name :</legend>
<form action="Employee5_After">
Item's name : <input type="text" name="prod_name" id="myProduct"><br>
<script>
$("#myProduct").autocomplete("autocompleteFromDb.jsp");
</script>
<input type="submit" value="Register">
</form>
</fieldset>
</body></html>
It forwards to this servlet :
Employee5_After
package controller.employee;
/**
* Retrieve the record of a given product by its name
* using hibernate
* #author X
*
*/
#WebServlet("/Employee5_After")
public class Employee5_After extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// grab the product's name that the user entered
String productName = request.getParameter("prod_name");
// create DB instance
DatabaseInventory inventory = new DatabaseInventory();
// get the details
String details = inventory.getProductDetailsByName(productName);
HttpSession session = request.getSession();
// forward answer to JSP
synchronized(session)
{
if (details != null) // then the product has been found
{
session.setAttribute("foundProd", details);
String addressPath = "/WEB-INF/results/employee/employeeResult5.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(addressPath);
dispatcher.forward(request, response);
}
}
}
}
That servlet is doing his stuff , and then forwards to a 2nd JSP ,called :
employeeResult5.jsp
<!-- Employee - get a description of a product by its name -->
<!DOCTYPE html>
<html>
<head><title>The details for the product you requested are below</title>
<link rel="stylesheet"
href="./css/styles.css"
type="text/css"/>
</head>
<body>
<h1>Here are the details from the product you request :</h1>
<h2>${foundProd}</h2>
<h1>We wish you well - bye bye!</h1>
<fieldset>
<legend>Go back to Employee's web-page</legend>
<form action="blablabla">
Press here to continue
</form>
</fieldset>
</body></html>
I guess that I can use the <% and %> in the JSP to do the logic side of the servlet (contacting to DB and retrieve data) . How can I avoid using a servlet in between , and just pass the data from one JSP to another JSP ?
You can use the request.redirect(URL) method to do it.
Or you can use request. forward(req, resp).
See example
Separate the business logic from the font end, there is no need to redirect to an intermediate servlet. The best practice is to put the business logic in a separate class and instantiate that class in the destination page. Here is one example:
mainPage.jsp - create the page similar to your employee5_searchByName.jsp. Now this page posts the data you enter.
Create a backing class called - dbData.java (DatabaseInventory in your case)- put all your database query here and functions to retrieve what your want. A function like public String searchText(String param) (similar to getProductDetailsByName(productName)) which will essentially fetch your search results from database.
Now the most important part - Instantiate this class in your destination SearchResults.jsp page and show whatever data you get in a manner similar to this:
<%#page import="mysource.dbData"%>
<%
searchParam = request.getParameter("searchStr");
dbData data = new dbData();
String result = data.searchText(searchParam);
%>
<HTML>
<BODY>
The result is: <% out.print(result); %>
</BODY>
</HTML>
The industry standard is to follow an MVC Architecture. Following that will create applications which are clear to understand and easy to maintain.
Try this code to forward with parameteres
<jsp:forward page="URL">
<jsp:param nama="param1" value="hello"/>
<jsp:param nama="param2" value="hello2"/>
<jsp:param nama="param3" value="hello3"/>
<jsp:param nama="param4" value="hello4"/>
.
........... and so on
</jsp:forward
I have learned in last class that jsp's custom tags are replaced with html content after evaluation of custom tag.
But putting this concept in practice, I faced following problem.
I have 3 div inside a jsp , 2 of them are static and middle div has a custom tag in it. So html content generated by middle div's custom tag should be replaced in middle div only.
But, output suggests something else, please point me out if there is something wrong with the code, or the statement used in starting of question needs some modification.
home.jsp
<div style="height: 80px; background-color: #FFA500;">
<%# include file="banner.html"%>
</div>
<div style="height: 450px;">
<connect:dbConnector user="root" password="" url="jdbc:mysql://localhost/musicstore" scope="session">
</connect:dbConnector>
<connect:Query where="select * from musicstore.songs;">
<ui:addTable name="musicList">
<c:forEach var="value" items="${result }">
<c:set scope="session" var="currentRow" value="${value }"></c:set>
<ui:addRow data="currentRow" scope="session">
</ui:addRow>
</c:forEach>
</ui:addTable>
</connect:Query>
</div>
<div style="height: 80px; background-color: #FFA500;">Footer
content</div>
html content that i can see on web browser are
<table border="1" name=" musicList ">
<tr> <td>Tum hi ho</td>
<td>Arjit Singh</td>
<td>45</td></tr>
<tr> <td>Manjha</td>
<td>Amit Trivedi</td>
<td>30</td></tr>
<tr> <td>Ranjhanna</td>
<td>A.R Rehman</td>
<td>25</td></tr>
<tr> <td>Sawar Loon</td>
<td>Monali Thankur</td>
<td>20</td></tr>
</table>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<div style="height: 80px; background-color: #FFA500;">
<img src="/WEB-INF/resources/music_banner.png" ></img>
</div>
<div style="height: 450px;">
</div>
<div style="height: 80px; background-color: #FFA500;">Footer
content</div>
</body>
</html>
AddRowTag.java
public class AddRowTag extends TagSupport {
// some getter, setter and other utility methods here.
#Override
public int doStartTag() throws JspException {
try {
System.out.println("AddRowTag--> doStartTag");
Row content = getDataToDisplay();
StringBuilder htmlContent = new StringBuilder();
htmlContent.append(startTableRow);
htmlContent.append(startTableData);
htmlContent.append(content.getTitle());
htmlContent.append(endableData);
htmlContent.append(startTableData);
htmlContent.append(content.getArtist());
htmlContent.append(endableData);
htmlContent.append(startTableData);
htmlContent.append(content.getPrice());
htmlContent.append(endableData);
htmlContent.append(endableRow);
System.out.println(htmlContent.toString());
pageContext.getResponse().getWriter().print(htmlContent);
} catch (IOException e) {
e.printStackTrace();
}
return SKIP_BODY;
}
}
Summarizing the problem:
Where(in context of location of placement of converted code(html code)) jsp custom tag code is placed in final html file.
What I need to modify in my current my current jsp code, if I want middle div should be updated on basis of custom tag.
Any suggestion/explanation is will be highly appreciated.
The tag should not write to the response directly. By doing that, it bypasses the JspWriter, which also writes to the response but buffers its output.
Replace
pageContext.getResponse().getWriter().print(htmlContent);
by
pageContext.getOut().print(htmlContent);