How can I make a search box with suggestions? - java

I want to have a search box for my java application which has suggestions as you type. As I have it right now, it only gives results after you press the button to search, but I want to have it just like the youtube website where it comes up with suggestions as you type. The problem is that with how slow the api requests are, it isn't possible to make a request for each new character entered into the search box. Here's the code for searching (There should be five suggestions shown):
private SearchListResponse search(String query)
{
try
{
YouTube.Search.List request = youtube.search().list("snippet").setKey(API_KEY);
SearchListResponse response = request.setMaxResults(5L).setQ(query).setType("video").execute();
return response;
} catch (IOException e)
{
e.printStackTrace();
return null;
}
}
And here's the basic search box I have right now:
JTextField searchBox = new JTextField(20);
container.add(searchBox);
JButton searchButton = new JButton("Search");
searchButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
search(searchBox.getText());
}
});
container.add(searchButton);

Related

Java Web Scraping wth Jaunt Library

I'm facing a problem with Java web scraping. This is the website: (http://www.bbc.com/sport/football/teams/liverpool)
From here I want to scrape the Headlines data.
Note: I'm using Jaunt Library.
public class News extends JFrame
{
private String title;
private JLabel labelText2;
News()
{
setSize(800, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
labelText2 = new JLabel();
setLayout(null);
labelText2.setBounds(10, 10, 550, 20);
add(labelText2);
}
public void Club_News()
{
try {
UserAgent userAgent = new UserAgent();
userAgent.visit("http://www.bbc.com/sport/football/teams/liverpool");
String div = userAgent.doc.findFirst(
"<div id=\"more-headlines\" class=\"mod mod-separator\">").innerHTML();
labelText2.setText("Latest News Headlines: " + div);
} catch (JauntException e) {
System.err.println(e);
}
}
}
You need to call your Club_News() method. You can make it the last statement in your constructor:
add(labelText2); // existing last line
Club_News(); // new method call
To make errors obvious, add a line to your catch block at the end of Club_News():
System.err.println(e); // existing error handling
labelText2.setText(e.toString()); // new hint

JComboBox ActionListener not working after removeAllItems() was used

I have two JComboBoxes; one removes all items in the other if it's already populated and then adds a new set of items, and the second fires an event that gets information from a database using the selected item. The problem occurs after the first combo box does its thing removing the items and adding new ones; when I select any of the items in the second JComboBox, the event that fires doesn't happen anymore.
Below I have provided snippets of my code:
The first combo box
cmbIDs.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
selection = (String)cmbIDs.getSelectedItem();
if (!(selection.equals("Select an username")))//current selection in combobox is stored as string
{
comboActivate(selection);
if (!unitC.getText().equals("")){
unitC.setText("");
}
if (!lecturer.getText().equals("")){
lecturer.setText("");
}
if (!(courseD.getText().equals("Not Enrolled"))){
populateUnits(selection);
}
}
else{
JOptionPane.showMessageDialog(null,"Please select a Surname.");
}
}
});
Removing the items inside populateUnits(String selectionID):
try
{
units.removeAllItems();
units.addItem("Select a Unit");
}
catch (NullPointerException npe)
{
units.addItem("Select a Unit");
}
After this instructions are sent through a client to a server where a db is queried and the server replies with information which is then added to the second JComboBox. I assure you also that the items are added to the JComboBox after removeAllItems() is used.
The second jComboBox:
units.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ue)
{
uSelect = (String)units.getSelectedItem();
if (!(uSelect.equals("Select a Unit")))//current selection in combobox is stored as string
{
System.out.println(uSelect);
unitActivate(uSelect);
}
else
{
JOptionPane.showMessageDialog(null,"Please select a Unit.");
}
}
});
It looks like your code never gets a fresh set of items from the database, so the user can never select anything other than "Select an Unit", which your second code block ignores.
it work for me
try {
boxListMaterial.removeActionListener(controller);
boxListMaterial.removeAllItems();
}catch (Exception e){}
boxListMaterial.addActionListener(controller);
Controller - ActionListener*

JButton ActionListener Integration Issue

I am relatively new to Java and recently I have been working on a GUI based html parser.
The interface is simple, consisting of:
JTextField for entering a search term
JButton b1 to initiate the search
JButton b2 to exit
JButton b3 to display an URL in the browser using cmd prmt.
The problem arises with b3.
Here is a code sample:
while (mstyle2.find())
{
String s=mstyle2.group(0);
String pattern = "(?i)(<cite.*?>)(.+?)(</cite>)";
String updated = s.replaceAll(pattern, "$2");
String pattern2 = "(?i)(<b>)(.+?)(</b>)";
String updated2 = updated.replaceAll(pattern2, "$2");
String pattern3 = "(http://)";
boolean c=true;
String updated32 = updated2.replaceAll(pattern3, "");
String pattern32 = "(https://)";
final String updated3 = updated32.replaceAll(pattern32,"");
try {
URL url2 = new URL("http://"+updated3);
URLConnection conne = url2.openConnection();
conne.connect();
} catch (MalformedURLException e) {
c=false;
} catch (IOException e) {
c=false;//checks validity of url
}
if(c) {
Process p=Runtime.getRuntime().exec("cmd /c start http://"+updated3);
}
}
The idea is that the following command line should only be executed when b3 is pressed. Otherwise the loop will not execute, and remain in that line until the button is pressed.
Process p=Runtime.getRuntime().exec("cmd /c start http://"+updated3);
However, I cannot find any viable way to properly implement the ActionListener method in order to make this possible.
In most of my tries, once b3 is pressed, all link open at once (thus beating the purpose of the b3) and not one by one with every click of b3.
Solution
JButtons has a method called addActionListener(). This method allows you to attach a runnable to a button, so the code is only called when it is clicked.
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
// Your code here!
}
});
What is this doing?
Well this is adding a new ActionListener object to your button. However, ActionListener has an abstract method, actionPeformed that needs an implementation. You are simply providing the code in the constructor.

"Concatenating" andFilter and orFilter for RowFilter

I have a JTable with four columns, the first one containing either a number or a text, the other three only text. I'm trying to filter this table with the help of a RowFilter:
sorter = new TableRowSorter<TableModel>(myOwnTableModel);
The checkboxFilter I got works well enough:
sorter.setRowFilter(RowFilter.regexFilter("^[0-9]$", 0));
This sorter is activated or deactivate depending on a checkbox that is either set or not.
The second filtering happens if a user puts some text in a textfield. For itself, this works fine already:
String regex = "(?i)" + Pattern.quote(s); // s = input Text of user
sorter.setRowFilter(RowFilter.regexFilter(regex, 1,2,3));
What I can't do, is to activate both filters at the same time. Maybe I'm thinking way too far, my idea has been to "concatenate" the two filters, the checkboxFilter should be "and" the other "or". I tried several things, to me the most promising looked something like:
String regex = "(?i)" + Pattern.quote(s);
bookFilter = RowFilter.regexFilter(regex, 1,2,3);
sorter.setRowFilter(bookFilter.andFilter(Arrays.asList(
RowFilter.regexFilter("^[0-9]$", 0))));
Unfortunately, this doesn't lead to any usable result. Any ideas appreciated :)
The solution is to add an ActionListener to the JCheckBox to update the filter state if the checkbox is toggled and to add a DocumentListener to the JTextField's underlying Document to update the filter state if the contents of the field is updated.
The other bug in your code is that you are calling the static andFilter method on your bookFilter instance and are only passing in the newly constructed regex filter (i.e. you are only passing in one parameter to andFilter). The correct usage is:
RowFilter andFilter = RowFilter.andFilter(filter1, filter2, etc);
Example Event Listeners
JCheckBox cb = ...
cb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
updateFilters();
}
});
JTextField tf = ...
tf.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) { updateFilters(); }
public void removeUpdate(DocumentEvent e) { updateFilters(); }
publci void changedUpdate(DocumentEvent e) { updateFilters(); }
});
... and then define your updateFilters() method to install a new filter based on when the checkbox is selected and whether the text field is empty or not.
Example Filter Update Method
public void updateFilters() {
if (cb.isSelected()) {
if (tf.getText().length() > 0) {
// Both filters active so construct an and filter.
sorter.setRowFilter(RowFilter.andFilter(bookFilter, checkBoxFilter));
} else {
// Checkbox selected but text field empty.
sorter.setRowFilter(checkBoxFilter);
}
} else if (tf.getText().length() > 0) {
// Checkbox deselected but text field non-empty.
sorter.setRowFilter(bookFilter);
} else {
// Neither filter "active" so remove filter from sorter.
sorter.setRowFilter(null); // Will cause table to re-filter.
}
}

HtmlUnit HtmlImageInput.click() not working?

I am kinda new to HtmlUnit and am having some trouble getting a form to submit with HtmlImageInput.click(). When I call the method, nothing seems to happen, no form submission, no round trip to the server, or anything, as far as I can tell. The method returns immediately, returning the current page.
There's no Javascript event handler attached to the image input. It's just a plain old vanilla image input, nothing special going on. The input is initially set to disabled when the page is loaded, and then gets enabled as the user interacts with certain AJAXy elements within the page. But by the time I click on the input, it has already been enabled, so I don't think it's an AJAX issue.
Anybody have an idea of what is going on? Runnable source code pasted below.
Thanks,
Matthew
import java.io.*;
import java.util.*;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.*;
import org.w3c.dom.*;
public class Test {
public static void main(String args[]) {
try {
WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
webClient.setThrowExceptionOnScriptError(false);
HtmlPage page = webClient.getPage("http://us.megabus.com");
System.out.println("got the page");
HtmlForm form = page.getFormByName("ctl01");
System.out.println("got the form");
HtmlSelect select = form.getSelectByName("SearchAndBuy1$ddlLeavingFrom");
select.click();
System.out.println("clicked the select");
HtmlOption option = select.getOptionByValue("13");
option.click();
System.out.println("clicked the option...going to sleep");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
select = form.getSelectByName("SearchAndBuy1$ddlTravellingTo");
select.click();
System.out.println("clicked the select 2");
option = select.getOptionByValue("37");
option.click();
System.out.println("clicked the option 2...going to sleep");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
HtmlImage image = (HtmlImage)page.getElementById("SearchAndBuy1_imgOutboundDate");
image.click();
System.out.println("clicked the image");
String month = "April";
String date = "09";
HtmlTable table = (HtmlTable)page.getElementById("SearchAndBuy1_calendarOutboundDate");
HtmlTableRow row = ((HtmlTable)table.getCellAt(0, 0).getChildElements().iterator().next()).getRow(0);
String monthString = row.getCell(1).getTextContent();
monthString = monthString.substring(0, monthString.indexOf(' '));
while(!monthString.equals(month)) {
row.getCell(2).getChildElements().iterator().next().click();
System.out.println("clicked to go to the next month");
try { Thread.sleep(15000); } catch(InterruptedException e) {}
table = (HtmlTable)page.getElementById("SearchAndBuy1_calendarOutboundDate");
row = ((HtmlTable)table.getCellAt(0, 0).getChildElements().iterator().next()).getRow(0);
monthString = row.getCell(1).getTextContent();
monthString = monthString.substring(0, monthString.indexOf(' '));
}
DomNodeList<HtmlElement> aList = table.getElementsByTagName("a");
for (int i = 0; i < aList.size(); i++) {
HtmlAnchor anchor = (HtmlAnchor)aList.get(i);
if (anchor.getAttribute("title").equals(DomElement.ATTRIBUTE_NOT_DEFINED) || anchor.getAttribute("title").equals(DomElement.ATTRIBUTE_VALUE_EMPTY))
throw new RuntimeException("DomElement ATTRIBUTE_NOT_DEFINED or ATTRIBUTE_VALUE_EMPTY");
if (anchor.getAttribute("title").equals(month + " " + date)) {
anchor.click();
try { Thread.sleep(15000); } catch(InterruptedException e) {}
break;
}
}
HtmlImageInput imageInput = (HtmlImageInput)page.getElementByName("SearchAndBuy1$btnSearch");
page = (HtmlPage)imageInput.click();
System.out.println("clicked search button");
} catch(FailingHttpStatusCodeException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ElementNotFoundException e) {
e.printStackTrace();
} catch(IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
}
That image is not an input field, it's just a plain old image:
<img id="SearchAndBuy1_imgOutboundDate" disabled="disabled" alt="calendar"
CausesValidation="False" src="images/icon_calendar.gif" style="border-width:0px;" />
There are no JS handlers specified there, so they must be attached elsewhere, and seems it's at the bottom of the page:
Sys.Application.add_init(function() {
$create(AjaxControlToolkit.PopupControlBehavior,
{"PopupControlID":"SearchAndBuy1_panelOutboundDate","Position":3,"dynamicServicePath":"/default.aspx","id":"SearchAndBuy1_pceImageOutboundDate"}, null, null, $get("SearchAndBuy1_imgOutboundDate"));
});
When your program clicks on the image, there is no form submit, just an AJAX call (presumably), so you're right, you don't get a new page back. But as your code proves (I just ran it with a debugger), the content of the HtmlPage has changed, since it now contains the calendar widget, which you were able to pull details from.
It can be a bit confusing knowing when you will get a net new HtmlPage back, but usually it's only when you would see a whole new page in the browser. I've never tried HtmlUnit against something like Gmail, but I suspect you might only ever deal with the one HtmlPage object, and everything takes places within it.

Categories

Resources