v0.3: Extension #3
@ -1,30 +1,80 @@
|
||||
import * as React from "react";
|
||||
|
||||
import "../style/search.scss";
|
||||
import Sugestion from "./Sugestion";
|
||||
import { Suggestion, SuggestionType } from "../types/suggestion";
|
||||
import getGoogleSuggestions from "../functions/getGoogleSuggestions";
|
||||
|
||||
class Search extends React.Component {
|
||||
interface State {
|
||||
sugestions: Suggestion[];
|
||||
}
|
||||
|
||||
class Search extends React.Component<{}, State> {
|
||||
|
||||
private searchInput = React.createRef<HTMLInputElement>()
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
sugestions: []
|
||||
};
|
||||
}
|
||||
|
||||
handleQuery(query: string) {
|
||||
this.search(query);
|
||||
}
|
||||
|
||||
search(query: string){
|
||||
search(query: string) {
|
||||
const url = new URL("https://duckduckgo.com/");
|
||||
const param = new URLSearchParams();
|
||||
param.append("q",query);
|
||||
param.append("q", query);
|
||||
url.search = param.toString();
|
||||
window.location.href = url.toString();
|
||||
}
|
||||
|
||||
onKeyDown(event: React.KeyboardEvent) {
|
||||
async sugest(input: string) {
|
||||
if (input === "") {
|
||||
this.setState({
|
||||
sugestions: []
|
||||
});
|
||||
} else {
|
||||
const results = await getGoogleSuggestions(input);
|
||||
|
||||
const newSuggestionState: Suggestion[] = results.suggestions.map((e) => {
|
||||
return {
|
||||
display: e,
|
||||
type: SuggestionType.QUERY
|
||||
};
|
||||
});
|
||||
|
||||
this.setState({
|
||||
sugestions: newSuggestionState
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
onKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
|
||||
if (event.key === 'Enter') {
|
||||
this.handleQuery(this.searchInput.current.value);
|
||||
} else if (event.key === "ArrowDown") {
|
||||
console.log("down");
|
||||
} else if (event.key === "ArrowUp") {
|
||||
console.log("up");
|
||||
}
|
||||
}
|
||||
|
||||
onChange() {
|
||||
this.sugest(this.searchInput.current.value);
|
||||
}
|
||||
|
||||
onSugestionClick(e: Suggestion) {
|
||||
if (e.type === SuggestionType.QUERY) {
|
||||
this.search(e.display);
|
||||
} else {
|
||||
window.location.href = e.url;
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,9 +82,21 @@ class Search extends React.Component {
|
||||
return <div className="search-component" >
|
||||
<input type="text"
|
||||
autoFocus
|
||||
onKeyDown={(e)=>this.onKeyDown(e)}
|
||||
onKeyDown={(e) => this.onKeyDown(e)}
|
||||
onChange={() => this.onChange()}
|
||||
ref={this.searchInput}
|
||||
/>
|
||||
autoComplete="off"
|
||||
/>
|
||||
|
||||
<div className="suggestion-area">
|
||||
{this.state.sugestions.map((e) => {
|
||||
return <Sugestion
|
||||
key={e.display}
|
||||
suggestion={e}
|
||||
onClick={() => { this.onSugestionClick(e); }}
|
||||
/>;
|
||||
})}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
17
src/components/Sugestion.tsx
Normal file
17
src/components/Sugestion.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import * as React from "react";
|
||||
|
||||
import "../style/suggestion.scss";
|
||||
import { Suggestion } from "../types/suggestion";
|
||||
|
||||
interface Props {
|
||||
suggestion: Suggestion;
|
||||
onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||
}
|
||||
|
||||
const Sugestion = (props: Props) => {
|
||||
return <div className="suggestion-component" onClick={props.onClick}>
|
||||
{props.suggestion.display}
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default Sugestion;
|
17
src/functions/getGoogleSuggestions.ts
Normal file
17
src/functions/getGoogleSuggestions.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import GoogleSuggestions from "../types/GoogleSuggestions";
|
||||
|
||||
export default async (query: string): Promise<GoogleSuggestions> => {
|
||||
const url = new URL(" http://suggestqueries.google.com/complete/search");
|
||||
const param = new URLSearchParams();
|
||||
param.append("q", query);
|
||||
param.append("client", "firefox"); // TODO check if the result are different on different clients
|
||||
url.search = param.toString();
|
||||
|
||||
const response = await fetch(url.toString());
|
||||
const results = await response.json();
|
||||
|
||||
return {
|
||||
query: results[0],
|
||||
suggestions: results[1]
|
||||
};
|
||||
};
|
@ -1,12 +1,19 @@
|
||||
.search-component{
|
||||
|
||||
text-align: center;
|
||||
margin-top: 2em;
|
||||
margin-bottom: 2em;
|
||||
margin: 2em auto 2em auto;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
|
||||
input[type=text]{
|
||||
width: 40%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
padding: 0.5em 1.5em;
|
||||
padding: 0.5em 1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.suggestion-area{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
12
src/style/suggestion.scss
Normal file
12
src/style/suggestion.scss
Normal file
@ -0,0 +1,12 @@
|
||||
.suggestion-component{
|
||||
padding: 0.2em 1em;
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 1px solid #d4d4d4;
|
||||
border-top: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #d4d4d4;
|
||||
}
|
||||
}
|
31
src/types/GoogleSuggestions.ts
Normal file
31
src/types/GoogleSuggestions.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Example if client == chrome:
|
||||
[
|
||||
"hello w",
|
||||
["hello world","hello world anime","hello world java","hello world c","hello world python","hello world html","hello world mhw","hello welcome home"],
|
||||
["","","","","","","",""],
|
||||
[],
|
||||
{
|
||||
"google:clientdata":{"bpc":false,"tlw":false},
|
||||
"google:suggestrelevance":[1250,1050,850,700,601,600,551,550],
|
||||
"google:suggesttype":["QUERY","QUERY","QUERY","QUERY","QUERY","QUERY","QUERY","QUERY"],
|
||||
"google:verbatimrelevance":851
|
||||
}
|
||||
]
|
||||
|
||||
Example if client == firefox:
|
||||
[
|
||||
"hello wo",
|
||||
[
|
||||
"hello world","hello world anime","hello world java","hello world c","hello world python","hello world html",
|
||||
"hello world mhw","hello world anime stream","hello world programm","hello world anime ger sub"
|
||||
]
|
||||
]
|
||||
*/
|
||||
|
||||
interface GoogleSuggestions {
|
||||
query: string;
|
||||
suggestions: string[];
|
||||
}
|
||||
|
||||
export default GoogleSuggestions;
|
12
src/types/Suggestion.ts
Normal file
12
src/types/Suggestion.ts
Normal file
@ -0,0 +1,12 @@
|
||||
enum SuggestionType {
|
||||
QUICK,
|
||||
QUERY
|
||||
}
|
||||
|
||||
interface Suggestion {
|
||||
display: string;
|
||||
type: SuggestionType;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export { SuggestionType, Suggestion };
|
Loading…
Reference in New Issue
Block a user