cluster_search_ui/commit
Cleaned up code.
author | Chris Dijkshoorn |
---|---|
Sat Dec 13 15:42:56 2014 +0100 | |
committer | Chris Dijkshoorn |
Sat Dec 13 15:42:56 2014 +0100 | |
commit | d0fc16e1ad5d3b116422e80a149908148813b548 |
tree | 16d07c3df8cd2554e10be068ed97952290aa9006 |
parent | 0d6e0aa440b1cab87aeb7712c2116a0d95f046b2 |
Diff style: patch stat
diff --git a/api/cluster_search_ui.pl b/api/cluster_search_ui.pl index 42cf75a..39fa995 100644 --- a/api/cluster_search_ui.pl +++ b/api/cluster_search_ui.pl @@ -1,371 +1,101 @@ -:- module(cluster_search_ui, [cluster_search/2]). +:- module(cluster_search_ui, []). -% http library +/** <module> Generation of web ui for cluster search + +This module is used for generating HTML elements for the ui for cluster +search. It is able to generate 4 different types of pages: + + * front - frontpage with a carousel of search examples + * results - results page depicting the search results + * result - one result and its metadata + * about - information about the system + +The ui variables are retrieved from rdf (e.g. rdf/rijksmuseum_ui.ttl). +*/ + +:- use_module(library(cluster_search_ui/web_ui_dcg)). +:- use_module(library(cluster_search_ui/settings)). :- use_module(library(http/http_ssl_plugin)). :- use_module(library(http/http_dispatch)). :- use_module(library(http/http_server_files)). -:- use_module(library(http/http_json)). -:- use_module(library(http/http_open)). -:- use_module(library(http/url_cache)). -:- use_module(library(http/http_parameters)). +:- use_module(library(http/html_write)). +:- use_module(library(http/html_head)). :- use_module(library(http/http_path)). - -% semweb modules +:- use_module(library(http/http_parameters)). :- use_module(library(semweb/rdf_db)). -:- use_module(library(semweb/rdf_label)). - -% register namespaces -:- rdf_register_prefix(rma, 'http://purl.org/collections/nl/rma/schema#'). -:- rdf_register_prefix(rmaterms, 'http://purl.org/collections/nl/rma/terms/'). -:- rdf_register_prefix(edm, 'http://www.europeana.eu/schemas/edm/'). -:- rdf_register_prefix(gvp, 'http://vocab.getty.edu/ontology#'). -:- rdf_register_prefix(aat, 'http://vocab.getty.edu/aat/'). -:- rdf_register_prefix(ulan, 'http://purl.org/vocabularies/getty/ulan/'). - -% util modules -:- use_module(library(cluster_search/rdf_cluster)). -:- use_module(library(cluster_search/rdf_search)). -:- use_module(library(cluster_search/iface_util)). -:- use_module(library(cluster_search_ui/settings)). -%:- use_module(library(cluster_search/search_statistics)). - -% search modules -:- use_module(library(cluster_search/graph_search)). - -% output modules -:- use_module(library(cluster_search/web_ui)). % construct url and define filesystem search paths http:location(fonts, cliopatria(fonts), []). http:location(img, cliopatria(img), []). -http:location(analysis, cliopatria(analysis), []). user:file_search_path(fonts, web(fonts)). user:file_search_path(img, web(img)). -user:file_search_path(analysis, web(analysis)). -:- http_handler(cliopatria(ui), web, []). -:- http_handler(cliopatria(search), results, []). +:- http_handler(cliopatria(search), search, []). +:- http_handler(cliopatria(results), results, []). :- http_handler(cliopatria(about), about, []). -:- http_handler(cliopatria(item), result, []). -:- http_handler(cliopatria(analytics), analytics, []). -:- http_handler(cliopatria(json), search_api, []). +:- http_handler(cliopatria(item), item, []). :- http_handler(fonts('.'), serve_files_in_directory(fonts), [prefix]). :- http_handler(img('.'), serve_files_in_directory(img), [prefix]). -:- http_handler(analysis('.'), serve_files_in_directory(analysis), [prefix]). - -%% search_api(+Request) -% -% Retrieves clusters of search results, according to the query. -% First it gets the url parameters, second it executes graph -% search algorithm. The resulting clusters are enriched with -% metadata, after which the data is prepared for output and -% outputted as json. -search_api(Request) :- - get_parameters(Request, Options), - cluster_search(Clusters, Options), - enrich(Clusters, EnrichedClusters, Options), - write_data(EnrichedClusters). - -%% get_parameters(+Request, -Options) -% -% Retrieves an option list of parameters from the url. -get_parameters(Request, Options) :- - http_parameters(Request, - [query(Query, [description('Entered Query'), optional(false)]) - ]), - Options = [query(Query)]. - -%% cluster_search(-Clusters, +Options) -% -% Executes a graph search algorithm according to given options. -% SearchResults is a list of score-resource pairs acquired by -% searching the RDF Graph. SearchState contains the search history -% including the search graph. -cluster_search(Clusters, Options) :- - option(query(Query), Options), - debug(query, 'cluster_search Query: ~p', [Query]), - SearchOptions = [graphOutput(spo)], - graph_search(Query, State, SearchOptions), - rdf_search_property(State, targets(SearchResults)), - OrganizeOptions = [groupBy(path)], - organize_resources(SearchResults, State, Clusters, OrganizeOptions). - -%% write_data(+Data, +Options) -% -% Write data in JSON format to output stream. -write_data(clusters(Clusters)) :- - clusters_to_json(Clusters, JsonClusters), - Json = json([clusters=JsonClusters]), - reply_json(Json). - -%% clusters_to_json(+Clusters, -JsonResults) -% -% Converts clusters to prolog terms appropriate for json output. -clusters_to_json([],[]). -clusters_to_json([Cluster|Clusters], [JsonCluster|JsonResults]) :- - cluster_info(Cluster, Path, ClusterItems), - length(ClusterItems, NumberOfResults), - items_to_json(ClusterItems, JsonItems), - path_to_json(Path, JsonPath), - JsonCluster = json([path=JsonPath, results=NumberOfResults, items=JsonItems]), - clusters_to_json(Clusters, JsonResults). - -cluster_info(Path - Items, Path, Items). - -%% items_to_json(+Clusters, -JsonResults) -% -% Converts items to prolog terms appropriate for json output. -items_to_json([], []). -items_to_json([item(Uri,ThumbnailUrl,Link,Title)|Results], [Item|JsonItems]) :- - Item = json([uri=Uri,thumb=ThumbnailUrl,link=Link,title=Title]), - items_to_json(Results, JsonItems). - -%% items_to_json(+Clusters, -JsonResults) -% -% Converts the path to prolog terms appropriate for json output. -path_to_json([], []). -path_to_json([step(Uri, Label)|Path], [JsonStep|JsonPath]) :- - JsonStep = json([uri=Uri, label=Label]), - path_to_json(Path, JsonPath). - - -/*************************************************** -* result organization -***************************************************/ - -%% organize_resources(+Targets, +Graph, -Data, +Options) -% -% Data is a structure containing Targets -organize_resources(Targets, State, clusters(Clusters), Options) :- - option(groupBy(GroupBy), Options), - option(start(Start), Options, 0), - option(end(End), Options, 100), - search_graph(State, SearchGraph), - group_targets_by_value(GroupBy, Targets, SearchGraph, Clusters0, Options), - cluster_select(Clusters0, Start, End, Clusters). -search_graph(State, Graph) :- - rdf_search_property(State, graph(Graph)), !. -search_graph(_, []). +:- set_setting_default(thumbnail:thumbnail_size, size(350,300)). +:- set_setting_default(thumbnail:medium_size, size(1280,1024)). +:- set_setting_default(search:image_filter, all). -%% group_items_by_value(+GroupBy, +Targets, +SearchGraph, -Clusters, +Options) +%% search(+Request) is det. % -% Clusters is a list of pairs with key is a value of GroupBy and -% the value a list of corresponding elements from Items. -group_targets_by_value(GroupBy, Targets, Graph, Clusters, Options) :- - memberchk(GroupBy, [path,spath]), - setting(search:search_path, Default), - option(searchPath(Method), Options, Default), - result_paths(Targets, Method, GroupBy, Graph, Pairs0), - keysort(Pairs0, Pairs), - group_pairs_by_key(Pairs, Clusters). +% Generate front page. +search(_Request) :- + reply_page(front, _Options). -%% result_paths(+Targets:score-resource, +Method, +Abstract, +Graph, -Items:item(Resource,Score,Path)) is det. +%% results(+Request) is det. % -% Add path between resource and query. -result_paths(Targets, Method, Abstract, Graph, Items) :- - empty_path_cache(Cache), - cached_result_paths(Targets, Method, Abstract, Graph, Cache, _, Items). - -cached_result_paths([], _, _, _, Cache, Cache, []). -cached_result_paths([Target|T], Method, Abstract, Graph, CacheIn, CacheOut, [Pair|Pairs]) :- - target(Target, URI, _Score), - ( cached_search_path(Method, URI, Graph, CacheIn, CacheTmp, Path0), - debug(spath, 'Abstract: ~p', [Abstract]), - abstract_path(Abstract, Path0, Path) - -> Pair = Path-(Target-Path0) - ; Pair = other-Target - ), - cached_result_paths(T, Method, Abstract, Graph, CacheTmp, CacheOut, Pairs). - - -%% abstract_path(+Type, +Path, -Abstract) is det. -% -% * Type = path -% Only abstract target. -% -% * Type = spath -% abstract full path to schema level - -abstract_path(path, [R|Rest0], Path) :- - iface_abstract_class(R, Class), !, - strip_rdf_value([Class|Rest0], Path0), - partial_schema_path(Path0, Path), - debug(spath, 'Should not happen PATH: ~p', [Path]). - -abstract_path(spath, Path, SPath) :- !, - (Path = [R] - -> iface_abstract_class(R, Class), - SPath = [Class] - ; strip_alignment(Path, Path1), - schema_path(Path1, SPath0), - canonical_path(SPath0, SPath) - ), - debug(spath, 'schema level path: ~p', [SPath]). - -%% cluster_select(+Clusters, +Start, +End, -ReducedClusters) -% -% Reduced Clusers only contains the items in Cluster starting at -% Start and ending at End. -cluster_select([], _, _, []). -cluster_select([C-Elems|T], Start, End, [C-Reduced|Rest]) :- - elem_select(Elems, Start, End, Reduced), - cluster_select(T, Start, End, Rest). - -%% elem_select(+List, +Start, +End, -SubList) -% -% SubList contains the elements from List starting at Start -% element up to the End element. -elem_select(Items, Start, End , Items) :- - Start > End, !. -elem_select(Items, 0, End, Selected) :- !, - length(Items, Total), - ( Total =< End - -> Selected = Items - ; length(Selected, End), - append(Selected, _, Items) - ). -elem_select(Items, Start, End, Selected) :- - length(Items, Total), - length(L0, Start), - append(L0, Rest, Items), - ( End >= Total - -> Selected = Rest - ; Length is End - Start, - length(Selected, Length), - append(Selected, _, Rest) - ). - -%% target(+Target, -URI, -Score). -% -% Split up target -target(Score-URI, URI, Score) :- !. -target(URI, URI, 1). - -/*************************************************** -* enrichment -***************************************************/ -enrich(clusters(Clusters), clusters(EnrichedClusters), Options) :- - enrich_clusters(Clusters, EnrichedClusters, Options). - -%% enrich_clusters(+Clusters, -EnrichedClusters, +Options) -% -% Enrich the clusters with info from the rdf store. -enrich_clusters([],[],_Options). -enrich_clusters([Cluster|Clusters], [PrettyPath - EnrichedItems|EnrichedClusters], Options) :- - cluster_info(Cluster, Path, ClusterItems), - prettify_path(Path, PrettyPath), - debug(enrich, 'Enrich Cluster: ~p', [ClusterItems]), - enrich_items(ClusterItems, EnrichedItems), - enrich_clusters(Clusters, EnrichedClusters, Options). - -%% prettify_path(+Path, -PrettyPath) -% -% Add the label to uris in the path. -prettify_path([], []). -prettify_path([Uri|Path], [step(Uri,Label)|PrettyPath]) :- - rdf_display_label(Uri, _, Label), - prettify_path(Path, PrettyPath). - -%% enrich_items(+Items, -EnrichedItems) -% -% Add a url of the thumbnail, a link to the resultpage and the -% title to an item. -enrich_items([], []). -enrich_items([_Score-Uri-_List|Results], [item(Uri,ThumbnailUrl,Link,Title)|EnrichedResults]) :- - thumbnail_url(Uri, ThumbnailUrl), - get_short_title(Uri, 36, Title), - concat('item?uri=', Uri, PartLink), - http_absolute_location(root(PartLink), Link, []), - debug(enrich_item, 'Uri: ~p ThumbnailUrl: ~p Link: ~p Title: ~p', - [Uri,ThumbnailUrl,Link,Title]), - enrich_items(Results, EnrichedResults). - -:- multifile cliopatria:thumbnail_url/2. - -%% thumbnail_url(+Uri, -ImageUrl) -% -% * Check if image is present, if so, return request url. -% * If the image is not present, check if present at url. -% * If not present, but a isShownBy present in database, remove -% isShownBy triple. -% * If not present in cache, database and at url, send image stub. -thumbnail_url(Uri, ImageUrl) :- - cliopatria:thumbnail_url(Uri, ImageUrl), - !. - -thumbnail_url(Uri, ImageUrl) :- - rdf(Aggregation, edm:aggregatedCHO, Uri), - rdf(Aggregation, edm:isShownBy, Image), - url_cached(Image, file(_)), - !, - concat('cache/fit?uri=', Image, RequestUrl), - http_absolute_location(root(RequestUrl), ImageUrl, []). - -thumbnail_url(Uri, ImageUrl) :- - rdf(Aggregation, edm:aggregatedCHO, Uri), - rdf(Aggregation, edm:isShownBy, Image), - https_header_response(Image, Status), - Status == 200, - !, - concat('cache/fit?uri=', Image, RequestUrl), - http_absolute_location(root(RequestUrl), ImageUrl, []). - -thumbnail_url(Uri, Stub) :- - rdf(Aggregation, edm:aggregatedCHO, Uri), - rdf(Aggregation, edm:isShownBy, Image), - !, - rdf_retractall(Uri, rma:imageURL, Image), - http_absolute_location(img('/stub.png'), Stub, []). - -thumbnail_url(_, Stub) :- http_absolute_location(img('/stub.png'), Stub, []). - -%% https_header_response(+URL, -Status) -% -% Return the response header of input URL. -https_header_response(URL, Status) :- - http_open(URL, In, - [method(head), - status_code(Status), - cert_verify_hook(ssl_verify) - ]), - close(In). - -:- public ssl_verify/5. +% Generate results page. +results(Request) :- + get_parameters(Request, Options), + reply_page(results, Options). -%% ssl_verify(+SSL, +ProblemCert, +AllCerts, +FirstCert, +Error) +%% restult(+Request) is det. % -% Currently we accept all certificates. -ssl_verify(_SSL, - _ProblemCertificate, _AllCertificates, _FirstCertificate, - _Error). +% Generate a page showing a result with its metadata. +item(Request) :- + get_parameters(Request, Options), + reply_page(result, Options). -%% get_short_title(+Uri, +DesiredLength, -Title) +%% about(+Request) is det. % -% Returns a title which is shorter or equal the desired length. -% Returns the URI if no title is found. -get_short_title(Uri, DesiredLength, Title) :- - rdf(Uri, dc:title, literal(lang(_,Title))), - atom_length(Title, CurrentLenght), - CurrentLenght =< DesiredLength, - !. -get_short_title(Uri, DesiredLength, Result) :- - rdf(Uri, dc:title, literal(lang(_,Title))), - atom_chars(Title, List), - shorten_list(List, DesiredLength, ShortList), - atom_chars(ShortTitle, ShortList), - atom_concat(ShortTitle, '...', Result), - !. -get_short_title(Uri, _, Uri). +% Generate about page. +about(Request) :- + get_parameters(Request, Options), + reply_page(about, Options). -%% shorten_list(+List, +DesiredLength, -ShortList) is det. +%% get_parameters(+Request, -Options) % -% Shorten a list to the desired length. -shorten_list(List, Length, ShortList) :- - shorten_list(List, Length, 0, ShortList). -shorten_list([],_,_,[]) :- !. -shorten_list(_,NrResults,NrResults,[]). -shorten_list([H|T], Length, N, [H|ShortList]) :- - NNew is N + 1, - shorten_list(T, Length, NNew, ShortList). +% Retrieves an option list of parameters from the url. +get_parameters(Request, Options) :- + http_parameters(Request, + [query(Query, [description('Entered Query'), optional(true)]), + uri(URI, [description('URI of the item'), optional(true)]) + ]), + Options = [query(Query), uri(URI)]. + +%% reply_page(+Page, +Options) +% +% Replies the html page corresponding to the type of page and +% Request. +reply_page(Page, Options) :- + setting(search:ui, UI), + rdf(UI, ui:iconLocation, literal(IconName)), + http_absolute_location(icons(IconName), Icon, []), + html_resource(css('search.css'), [requires([css('bootstrap.min.css')])]), + reply_html_page( + [ + \title(Page, Options), + link([href(Icon),rel('shortcut icon')]), + meta([name('viewport'),content('width=device-width, initial-scale=1.0')]) + ], + [\html_requires(css('search.css')), + \navigation_bar(Page), + \scripts(Page), + \content(Page, Options) + ]). diff --git a/lib/cluster_search_ui/settings.pl b/lib/cluster_search_ui/settings.pl index 701d351..cc08003 100644 --- a/lib/cluster_search_ui/settings.pl +++ b/lib/cluster_search_ui/settings.pl @@ -15,9 +15,5 @@ 'Setting indicating the level of enrichment of results.'). :- setting(search:ui, uri, rui:rijksmuseumUI, 'Default URI defining the UI for search'). -:- setting(search:graphSearchCache, boolean, true, - 'Cache graph search results'). -:- setting(search:graphSearchCacheSize, nonneg, 50, - 'Maximum searches kept in cache (0 is unbound)'). :- setting(search:annotate, boolean, false, 'Indicate the possibility of annotating search result.'). diff --git a/lib/cluster_search_ui/web_ui_dcg.pl b/lib/cluster_search_ui/web_ui_dcg.pl index 5842f50..602ee0b 100644 --- a/lib/cluster_search_ui/web_ui_dcg.pl +++ b/lib/cluster_search_ui/web_ui_dcg.pl @@ -5,17 +5,15 @@ navigation_bar/3 ]). +:- use_module(library(cluster_search_ui/settings)). +:- use_module(applications(annotation)). :- use_module(library(http/html_write)). :- use_module(library(http/http_path)). -:- use_module(library(http/http_path)). :- use_module(library(http/url_cache)). :- use_module(library(http/http_open)). -:- use_module(library('http/http_dispatch')). +:- use_module(library(http/http_dispatch)). :- use_module(library(semweb/rdf_db)). -:- use_module(library(cluster_search/settings)). :- use_module(cliopatria(components/label)). -:- use_module(library(cluster_search/search_statistics)). -:- use_module(applications(annotation)). %% content(+Type, +Options) @@ -62,46 +60,6 @@ content(about, _) --> </div> |}). -content(analytics, _) --> - {debug(analytics, 'Querying for statistics.', []), - get_dataset_statistics_minimal(DatasetStatistics), - %DatasetStatistics = [dataset_statistics(rma, 'Rijksmuseum Collection', [['stub', 36]])], - %http_absolute_location(analysis('analysis_results.csv'), AnalysisCSV, []), - %concat('areaChart("', AnalysisCSV, FunctionArea0), - %concat(FunctionArea0, '");', FunctionArea), - %concat('barChart("', AnalysisCSV, FunctionBar0), - %concat(FunctionBar0, '");', FunctionBar), - debug(analytics, 'The statistics: ~p', [DatasetStatistics]) - }, - html([div(class('container-fluid'), - div(class('row'), - [div(class('col-sm-3 col-md-2 sidebar'), - \navigation_analytics), - div(['data-spy'('scroll'), 'data-target'('.sidebar'), class('col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 col-md-8 col-md-offset-2')], - [div([h1('Statistics'), - p(class('lead'),'Get (some) insight in the loaded collection.')]), - %div(id('query-overview'), - % [a([class('anchor'), id('query-overview-anchor')],''), - % h2('Query Overview')]), - %div(id('query-matches'), - % [a([class('anchor'), id('query-matches-anchor')],''), - % h2('Query Matches')]), - %div(id('analytics-test'), - % [a([class('anchor'), id('analytics-test-anchor')],''), - % h2('Analytics Test'), - % \analytics_html]), - div(id('dataset-statistics'), - [a([class('anchor'), id('dataset-statistics-anchor')],''), - h2('Dataset Statistics'), - \dataset_statistics(DatasetStatistics)]) - ]) - ])), - %script(src('https://apis.google.com/js/client.js?onload=handleClientLoad'), ''), - \load_javascript(analytics)]). - %script(FunctionArea), - %script(FunctionBar)]). - %html([div(id('results'),''),script('analytics();')]). - content(results, Options) --> results_page(cluster, Options). @@ -123,14 +81,6 @@ get_annotation_options(Uri, AnnotationOptions) :- get_image_options(Uri, ImageUrl) :- image_url(Uri, ImageUrl). -%analytics_html --> -% html({|html|| -% <!-- The 2 Buttons for the user to interact with --> -% <button id="authorize-button" style="visibility: -% hidden">Authorize</button><br/> -% <button id="make-api-call-button" style="visibility: hidden">Get Visits</button> |}). -% - %% get_carousel_items(-CarouselItems) % @@ -248,40 +198,24 @@ query_title(Uri, Title) :- scripts(front) --> html([\load_javascript(jquery), \load_javascript(bootstrap), - \load_javascript(type_ahead), - \load_javascript(search), - \load_javascript(google_analytics)]). + \load_javascript(search)]). scripts(results) --> html([\load_javascript(jquery), \load_javascript(bootstrap), - \load_javascript(type_ahead), \load_javascript(search), \load_javascript(pagination), - \load_javascript(thumbnail), - \load_javascript(google_analytics)]). + \load_javascript(thumbnail)]). scripts(result) --> html([\load_javascript(jquery), \load_javascript(bootstrap), - \load_javascript(type_ahead), - \load_javascript(search), - \load_javascript(google_analytics)]). + \load_javascript(search)]). scripts(about) --> html([\load_javascript(jquery), \load_javascript(bootstrap), - \load_javascript(type_ahead), - \load_javascript(search), - \load_javascript(google_analytics)]). - -scripts(analytics) --> - html([\load_javascript(jquery), - \load_javascript(bootstrap), - \load_javascript(d3js), - \load_javascript(type_ahead), - \load_javascript(search), - \load_javascript(google_analytics)]). + \load_javascript(search)]). %% load_javascript(+Script) % @@ -291,11 +225,6 @@ load_javascript(jquery) --> load_javascript(bootstrap) --> {http_absolute_location(js('bootstrap.min.js'), JavaScriptBootstrap, [])}, html(script(src(JavaScriptBootstrap),'')). -load_javascript(d3js) --> - html(script(src('http://d3js.org/d3.v3.js'),'')). -load_javascript(type_ahead) --> - {http_absolute_location(js('typeahead.min.js'), JavaScriptTypeahead, [])}, - html(script(src(JavaScriptTypeahead),'')). load_javascript(search) --> {http_absolute_location(js('search.js'), JavaScriptSearch, [])}, html(script(src(JavaScriptSearch),'')). @@ -305,25 +234,18 @@ load_javascript(pagination) --> load_javascript(thumbnail) --> {http_absolute_location(js('thumbnail.js'), JavaScriptThumbnail, [])}, html(script(src(JavaScriptThumbnail),'')). -load_javascript(google_analytics) --> - {http_absolute_location(js('google_analytics.js'), JavaScriptGoogleAnalytics, [])}, - html(script(src(JavaScriptGoogleAnalytics),'')). -load_javascript(analytics) --> - {http_absolute_location(js('analytics.js'), JavaScriptAnalytics, [])}, - html(script(src(JavaScriptAnalytics),'')). %% navigation_bar(+Page) % % Generates the navigation bar for the given page. navigation_bar(front) --> - {http_location_by_id(web, HttpWeb), + {http_location_by_id(search, HttpWeb), http_location_by_id(results, HttpSearch), http_location_by_id(about, HttpAbout), - http_location_by_id(analytics, HttpAnalytics), setting(search:ui, UI), rdf(UI, dcterms:title, literal(lang(en, Title))) }, - html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| + html({|html(HttpWeb, HttpSearch, HttpAbout, Title)|| <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> @@ -334,7 +256,6 @@ navigation_bar(front) --> <div class="collapse navbar-collapse navbar-sign-collapse"> <ul class="nav navbar-nav navbar-right"> - <li><a href="HttpAnalytics">Statistics</a></li> <li><a href="HttpAbout">About</a></li> </ul> <form class="navbar-form" action="HttpSearch" autocomplete="off"> @@ -350,14 +271,13 @@ navigation_bar(front) --> |}). navigation_bar(about) --> - {http_location_by_id(web, HttpWeb), + {http_location_by_id(search, HttpWeb), http_location_by_id(results, HttpSearch), http_location_by_id(about, HttpAbout), - http_location_by_id(analytics, HttpAnalytics), setting(search:ui, UI), rdf(UI, dcterms:title, literal(lang(en, Title))) }, - html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| + html({|html(HttpWeb, HttpSearch, HttpAbout, Title)|| <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> @@ -368,7 +288,6 @@ navigation_bar(about) --> <div class="collapse navbar-collapse navbar-sign-collapse"> <ul class="nav navbar-nav navbar-right"> - <li><a href="HttpAnalytics">Statistics</a></li> <li class="active"><a href="HttpAbout">About</a></li> </ul> <form class="navbar-form" action="HttpSearch" autocomplete="off"> @@ -383,53 +302,10 @@ navigation_bar(about) --> </nav> |}). -navigation_bar(analytics) --> - {http_location_by_id(web, HttpWeb), - http_location_by_id(results, HttpSearch), - http_location_by_id(about, HttpAbout), - http_location_by_id(analytics, HttpAnalytics), - setting(search:ui, UI), - rdf(UI, dcterms:title, literal(lang(en, Title))) - }, - html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| - <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="HttpWeb">Title</a> - </div> - - <div class="collapse navbar-collapse navbar-sign-collapse"> - <ul class="nav navbar-nav navbar-right"> - <li class="active"><a href="HttpAnalytics">Statistics</a></li> - <li><a href="HttpAbout">About</a></li> - </ul> - <form class="navbar-form" action="HttpSearch" autocomplete="off"> - <div class="input-group search-form"> - <input type="search" class="form-control typeahead" name="query"> - <span class="input-group-btn"> - <button type="submit" class="btn btn-default">Search</button> - </span> - </div><!-- /input-group --> - </form> - </div> - </nav> - |}). - navigation_bar(results) --> navigation_bar(front). navigation_bar(result) --> navigation_bar(front). -navigation_analytics --> - html({|html|| - <ul class="nav nav-sidebar"> - <!--<li class="active"><a href="#query-overview-anchor">Query Overview</a></li>--> - <!--<li><a href="#query-matches-anchor">Query Matches</a></li>--> - <li><a href="#dataset-statistics-anchor">Dataset</a></li> - </ul> - |}). - %% metadata(+ListOfPredicateObjectPairs) % % Loops through the list of metadata fields @@ -447,61 +323,6 @@ format_metadata(Predicate, Object) --> dd(\rdf_link(Object, [resource_format(nslabel)])) ]). -%% dataset_statistics(+Statistics) -% -% Loops through the list of dataset statistics -dataset_statistics(Statistics) --> - html([ul(class('nav nav-tabs'),\navigation_tabs(Statistics)), - div(class('tab-content'),\tab_tables(Statistics))]). - -%% navigation_tabs(+Statistics) -% -% Loops through the list of dataset statistics -navigation_tabs([First|More]) --> - html([\first_tab(First), - \more_tabs(More)]). - -first_tab(dataset_statistics(ID, Name, _Statistics)) --> - {concat('#', ID, IDRef)}, - html(li(class('active'), a([href(IDRef), 'data-toggle'('tab')], Name))). - -more_tabs([]) --> []. -more_tabs([dataset_statistics(ID, Name, _Statistics)|T]) --> - {concat('#', ID, IDRef)}, - html(li(a([href(IDRef), 'data-toggle'('tab')], Name))), - more_tabs(T). - -%% tab_tables(+Statistics) -% -% Loops through the list of dataset statistics to create the -% contents, which are tables. -tab_tables([First|More]) --> - html([\first_tab_pane(First), - \more_tab_panes(More)]). - - -first_tab_pane(dataset_statistics(ID, _Name, Statistics)) --> - html(div([class('tab-pane fade in active'),id(ID)], - table(class('table table-striped'),\dataset_rows(Statistics)))). - -more_tab_panes([]) --> []. -more_tab_panes([Dataset|T]) --> - html(\tab_pane(Dataset)), - more_tab_panes(T). - -tab_pane(dataset_statistics(ID, _Name, Statistics)) --> - html(div([class('tab-pane fade data-table'),id(ID)], - table(class('table table-striped'), - \dataset_rows(Statistics)))). - -%% dataset_rowd(+Statistics) -% -% Loops through the list of dataset statistics -dataset_rows([]) --> []. -dataset_rows([[Property, Value]|T]) --> - html([tr([td(Property), td(Value)])]), - dataset_rows(T). - %% results_page(+TypeResults, +Results, +NumberOfResults) % % Generates a div were the results are shown. diff --git a/web/js/analytics.js b/web/js/analytics.js deleted file mode 100644 index ded8985..0000000 --- a/web/js/analytics.js +++ /dev/null @@ -1,164 +0,0 @@ -/* Analytics -* Code for sending information to google analytics and calling the analytics api for aggregates. -*/ -//Sidebar link switching -$(" .nav-sidebar li a").click(function() { - $(" .nav-sidebar li ").removeClass('active'); - var $parent = $(this).parent(); - if (!$parent.hasClass('active')) { - $parent.addClass('active'); - } -}); - -function barChart(filePath) { - var margin = {top: 20, right: 20, bottom: 80, left: 40}, - width = 960 - margin.left - margin.right, - height = 500 - margin.top - margin.bottom; - - var x = d3.scale.ordinal() - .rangeRoundBands([0, width], 0.1); - - var y = d3.scale.linear() - .range([height, 0]); - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left") - .ticks(10); - - var svg = d3.select("#query-matches").append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - d3.csv(filePath, type, function(error, data) { - var start = 0; - var stop = 50; - data = data.slice(start,stop); - - x.domain(data.map(function(d) { return d.query; })); - y.domain([0, d3.max(data, function(d) { return d.number; })]); - - svg.append("g") - .attr("class", "x axis bar-axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis) - .selectAll("text") - .style("text-anchor", "end") - .attr("dx", "-.8em") - .attr("dy", ".15em") - .attr("transform", function(d) { - return "rotate(-65)" - }); - - svg.append("g") - .attr("class", "y axis") - .call(yAxis) - .append("text") - .attr("transform", "rotate(-90)") - .attr("y", 6) - .attr("dy", ".71em") - .style("text-anchor", "end") - .text("Number of times the query is used at the RMA site"); - - //function (d) { return "bar " + d.direct_match }; - function match_class(direct_match, direct_match_ic) { - if(direct_match_ic == "true") { - return "bar direct_match_ic"; - } else if (direct_match == "true") { - return "bar direct_match"; - } - return "bar no_match"; - } - - - svg.selectAll(".bar") - .data(data) - .enter().append("rect") - .attr("class", function(d) { return match_class(d.direct_match, d.direct_match_ic); }) - .attr("x", function(d) { return x(d.query); }) - .attr("width", x.rangeBand()) - .attr("y", function(d) { return y(d.number); }) - .attr("height", function(d) { return height - y(d.number); }); - - }); - - - function type(d) { - d.number = +d.number; - d.direct_match - return d; - } -} - -function areaChart(filePath) { - var margin = {top: 20, right: 20, bottom: 30, left: 50}, - width = 1024 - margin.left - margin.right, - height = 600 - margin.top - margin.bottom; - - var x = d3.scale.linear() - .range([0, width]); - - var y = d3.scale.linear() - .range([height, 0]); - - var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - - var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); - - var area = d3.svg.area() - .x(function(d) { return x(d.index); }) - .y0(height) - .y1(function(d) { return y(d.number); }); - - var svg = d3.select("#query-overview").append("svg") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - d3.csv(filePath, function(error, data) { - index = 0; - data.forEach(function(d) { - d.number = +d.number; - d.index = index; - index++; - }); - - var start = 0; - var stop = 2000; - data = data.slice(start,stop); - - x.domain([0, data.length]); - y.domain([0, d3.max(data, function(d) { return d.number; })]); - - svg.append("path") - .datum(data) - .attr("class", "area") - .attr("d", area); - - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + height + ")") - .call(xAxis); - - svg.append("g") - .attr("class", "y axis") - .call(yAxis) - .append("text") - .attr("transform", "rotate(-90)") - .attr("y", 6) - .attr("dy", ".71em") - .style("text-anchor", "end") - .text("Number of queries"); - }); -} \ No newline at end of file diff --git a/web/js/google_analytics.js b/web/js/google_analytics.js deleted file mode 100644 index 1c07e70..0000000 --- a/web/js/google_analytics.js +++ /dev/null @@ -1,12 +0,0 @@ -/* Analytics -* Code for sending information to google analytics and calling the analytics api for aggregates. -*/ - -// Send information to Google Analytics -//(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ -// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), -// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -//})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); -// -//ga('create', 'UA-47334744-1', 'vu.nl'); -//ga('send', 'pageview'); \ No newline at end of file diff --git a/web/js/typeahead.min.js b/web/js/typeahead.min.js deleted file mode 100644 index c085f8a..0000000 --- a/web/js/typeahead.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * typeahead.js 0.9.3 - * https://github.com/twitter/typeahead - * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT - */ - -!function(a){var b="0.9.3",c={isMsie:function(){var a=/(msie) ([\w.]+)/i.exec(navigator.userAgent);return a?parseInt(a[2],10):!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},bind:a.proxy,bindAll:function(b){var c;for(var d in b)a.isFunction(c=b[d])&&(b[d]=a.proxy(c,b))},indexOf:function(a,b){for(var c=0;c<a.length;c++)if(a[c]===b)return c;return-1},each:a.each,map:a.map,filter:a.grep,every:function(b,c){var d=!0;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?void 0:!1}),!!d):d},some:function(b,c){var d=!1;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?!1:void 0}),!!d):d},mixin:a.extend,getUniqueId:function(){var a=0;return function(){return a++}}(),defer:function(a){setTimeout(a,0)},debounce:function(a,b,c){var d,e;return function(){var f,g,h=this,i=arguments;return f=function(){d=null,c||(e=a.apply(h,i))},g=c&&!d,clearTimeout(d),d=setTimeout(f,b),g&&(e=a.apply(h,i)),e}},throttle:function(a,b){var c,d,e,f,g,h;return g=0,h=function(){g=new Date,e=null,f=a.apply(c,d)},function(){var i=new Date,j=b-(i-g);return c=this,d=arguments,0>=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},tokenizeQuery:function(b){return a.trim(b).toLowerCase().split(/[\s]+/)},tokenizeText:function(b){return a.trim(b).toLowerCase().split(/[\s\-_]+/)},getProtocol:function(){return location.protocol},noop:function(){}},d=function(){var a=/\s+/;return{on:function(b,c){var d;if(!c)return this;for(this._callbacks=this._callbacks||{},b=b.split(a);d=b.shift();)this._callbacks[d]=this._callbacks[d]||[],this._callbacks[d].push(c);return this},trigger:function(b,c){var d,e;if(!this._callbacks)return this;for(b=b.split(a);d=b.shift();)if(e=this._callbacks[d])for(var f=0;f<e.length;f+=1)e[f].call(this,{type:d,data:c});return this}}}(),e=function(){function b(b){b&&b.el||a.error("EventBus initialized without el"),this.$el=a(b.el)}var d="typeahead:";return c.mixin(b.prototype,{trigger:function(a){var b=[].slice.call(arguments,1);this.$el.trigger(d+a,b)}}),b}(),f=function(){function a(a){this.prefix=["__",a,"__"].join(""),this.ttlKey="__ttl__",this.keyMatcher=new RegExp("^"+this.prefix)}function b(){return(new Date).getTime()}function d(a){return JSON.stringify(c.isUndefined(a)?null:a)}function e(a){return JSON.parse(a)}var f,g;try{f=window.localStorage,f.setItem("~~~","!"),f.removeItem("~~~")}catch(h){f=null}return g=f&&window.JSON?{_prefix:function(a){return this.prefix+a},_ttlKey:function(a){return this._prefix(a)+this.ttlKey},get:function(a){return this.isExpired(a)&&this.remove(a),e(f.getItem(this._prefix(a)))},set:function(a,e,g){return c.isNumber(g)?f.setItem(this._ttlKey(a),d(b()+g)):f.removeItem(this._ttlKey(a)),f.setItem(this._prefix(a),d(e))},remove:function(a){return f.removeItem(this._ttlKey(a)),f.removeItem(this._prefix(a)),this},clear:function(){var a,b,c=[],d=f.length;for(a=0;d>a;a++)(b=f.key(a)).match(this.keyMatcher)&&c.push(b.replace(this.keyMatcher,""));for(a=c.length;a--;)this.remove(c[a]);return this},isExpired:function(a){var d=e(f.getItem(this._ttlKey(a)));return c.isNumber(d)&&b()>d?!0:!1}}:{get:c.noop,set:c.noop,remove:c.noop,clear:c.noop,isExpired:c.noop},c.mixin(a.prototype,g),a}(),g=function(){function a(a){c.bindAll(this),a=a||{},this.sizeLimit=a.sizeLimit||10,this.cache={},this.cachedKeysByAge=[]}return c.mixin(a.prototype,{get:function(a){return this.cache[a]},set:function(a,b){var c;this.cachedKeysByAge.length===this.sizeLimit&&(c=this.cachedKeysByAge.shift(),delete this.cache[c]),this.cache[a]=b,this.cachedKeysByAge.push(a)}}),a}(),h=function(){function b(a){c.bindAll(this),a=c.isString(a)?{url:a}:a,i=i||new g,h=c.isNumber(a.maxParallelRequests)?a.maxParallelRequests:h||6,this.url=a.url,this.wildcard=a.wildcard||"%QUERY",this.filter=a.filter,this.replace=a.replace,this.ajaxSettings={type:"get",cache:a.cache,timeout:a.timeout,dataType:a.dataType||"json",beforeSend:a.beforeSend},this._get=(/^throttle$/i.test(a.rateLimitFn)?c.throttle:c.debounce)(this._get,a.rateLimitWait||300)}function d(){j++}function e(){j--}function f(){return h>j}var h,i,j=0,k={};return c.mixin(b.prototype,{_get:function(a,b){function c(c){var e=d.filter?d.filter(c):c;b&&b(e),i.set(a,c)}var d=this;f()?this._sendRequest(a).done(c):this.onDeckRequestArgs=[].slice.call(arguments,0)},_sendRequest:function(b){function c(){e(),k[b]=null,f.onDeckRequestArgs&&(f._get.apply(f,f.onDeckRequestArgs),f.onDeckRequestArgs=null)}var f=this,g=k[b];return g||(d(),g=k[b]=a.ajax(b,this.ajaxSettings).always(c)),g},get:function(a,b){var d,e,f=this,g=encodeURIComponent(a||"");return b=b||c.noop,d=this.replace?this.replace(this.url,g):this.url.replace(this.wildcard,g),(e=i.get(d))?c.defer(function(){b(f.filter?f.filter(e):e)}):this._get(d,b),!!e}}),b}(),i=function(){function d(b){c.bindAll(this),c.isString(b.template)&&!b.engine&&a.error("no template engine specified"),b.local||b.prefetch||b.remote||a.error("one of local, prefetch, or remote is required"),this.name=b.name||c.getUniqueId(),this.limit=b.limit||5,this.minLength=b.minLength||1,this.header=b.header,this.footer=b.footer,this.valueKey=b.valueKey||"value",this.template=e(b.template,b.engine,this.valueKey),this.local=b.local,this.prefetch=b.prefetch,this.remote=b.remote,this.itemHash={},this.adjacencyList={},this.storage=b.name?new f(b.name):null}function e(a,b,d){var e,f;return c.isFunction(a)?e=a:c.isString(a)?(f=b.compile(a),e=c.bind(f.render,f)):e=function(a){return"<p>"+a[d]+"</p>"},e}var g={thumbprint:"thumbprint",protocol:"protocol",itemHash:"itemHash",adjacencyList:"adjacencyList"};return c.mixin(d.prototype,{_processLocalData:function(a){this._mergeProcessedData(this._processData(a))},_loadPrefetchData:function(d){function e(a){var b=d.filter?d.filter(a):a,e=m._processData(b),f=e.itemHash,h=e.adjacencyList;m.storage&&(m.storage.set(g.itemHash,f,d.ttl),m.storage.set(g.adjacencyList,h,d.ttl),m.storage.set(g.thumbprint,n,d.ttl),m.storage.set(g.protocol,c.getProtocol(),d.ttl)),m._mergeProcessedData(e)}var f,h,i,j,k,l,m=this,n=b+(d.thumbprint||"");return this.storage&&(f=this.storage.get(g.thumbprint),h=this.storage.get(g.protocol),i=this.storage.get(g.itemHash),j=this.storage.get(g.adjacencyList)),k=f!==n||h!==c.getProtocol(),d=c.isString(d)?{url:d}:d,d.ttl=c.isNumber(d.ttl)?d.ttl:864e5,i&&j&&!k?(this._mergeProcessedData({itemHash:i,adjacencyList:j}),l=a.Deferred().resolve()):l=a.getJSON(d.url).done(e),l},_transformDatum:function(a){var b=c.isString(a)?a:a[this.valueKey],d=a.tokens||c.tokenizeText(b),e={value:b,tokens:d};return c.isString(a)?(e.datum={},e.datum[this.valueKey]=a):e.datum=a,e.tokens=c.filter(e.tokens,function(a){return!c.isBlankString(a)}),e.tokens=c.map(e.tokens,function(a){return a.toLowerCase()}),e},_processData:function(a){var b=this,d={},e={};return c.each(a,function(a,f){var g=b._transformDatum(f),h=c.getUniqueId(g.value);d[h]=g,c.each(g.tokens,function(a,b){var d=b.charAt(0),f=e[d]||(e[d]=[h]);!~c.indexOf(f,h)&&f.push(h)})}),{itemHash:d,adjacencyList:e}},_mergeProcessedData:function(a){var b=this;c.mixin(this.itemHash,a.itemHash),c.each(a.adjacencyList,function(a,c){var d=b.adjacencyList[a];b.adjacencyList[a]=d?d.concat(c):c})},_getLocalSuggestions:function(a){var b,d=this,e=[],f=[],g=[];return c.each(a,function(a,b){var d=b.charAt(0);!~c.indexOf(e,d)&&e.push(d)}),c.each(e,function(a,c){var e=d.adjacencyList[c];return e?(f.push(e),(!b||e.length<b.length)&&(b=e),void 0):!1}),f.length<e.length?[]:(c.each(b,function(b,e){var h,i,j=d.itemHash[e];h=c.every(f,function(a){return~c.indexOf(a,e)}),i=h&&c.every(a,function(a){return c.some(j.tokens,function(b){return 0===b.indexOf(a)})}),i&&g.push(j)}),g)},initialize:function(){var b;return this.local&&this._processLocalData(this.local),this.transport=this.remote?new h(this.remote):null,b=this.prefetch?this._loadPrefetchData(this.prefetch):a.Deferred().resolve(),this.local=this.prefetch=this.remote=null,this.initialize=function(){return b},b},getSuggestions:function(a,b){function d(a){f=f.slice(0),c.each(a,function(a,b){var d,e=g._transformDatum(b);return d=c.some(f,function(a){return e.value===a.value}),!d&&f.push(e),f.length<g.limit}),b&&b(f)}var e,f,g=this,h=!1;a.length<this.minLength||(e=c.tokenizeQuery(a),f=this._getLocalSuggestions(e).slice(0,this.limit),f.length<this.limit&&this.transport&&(h=this.transport.get(a,d)),!h&&b&&b(f))}}),d}(),j=function(){function b(b){var d=this;c.bindAll(this),this.specialKeyCodeMap={9:"tab",27:"esc",37:"left",39:"right",13:"enter",38:"up",40:"down"},this.$hint=a(b.hint),this.$input=a(b.input).on("blur.tt",this._handleBlur).on("focus.tt",this._handleFocus).on("keydown.tt",this._handleSpecialKeyEvent),c.isMsie()?this.$input.on("keydown.tt keypress.tt cut.tt paste.tt",function(a){d.specialKeyCodeMap[a.which||a.keyCode]||c.defer(d._compareQueryToInputValue)}):this.$input.on("input.tt",this._compareQueryToInputValue),this.query=this.$input.val(),this.$overflowHelper=e(this.$input)}function e(b){return a("<span></span>").css({position:"absolute",left:"-9999px",visibility:"hidden",whiteSpace:"nowrap",fontFamily:b.css("font-family"),fontSize:b.css("font-size"),fontStyle:b.css("font-style"),fontVariant:b.css("font-variant"),fontWeight:b.css("font-weight"),wordSpacing:b.css("word-spacing"),letterSpacing:b.css("letter-spacing"),textIndent:b.css("text-indent"),textRendering:b.css("text-rendering"),textTransform:b.css("text-transform")}).insertAfter(b)}function f(a,b){return a=(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),b=(b||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),a===b}return c.mixin(b.prototype,d,{_handleFocus:function(){this.trigger("focused")},_handleBlur:function(){this.trigger("blured")},_handleSpecialKeyEvent:function(a){var b=this.specialKeyCodeMap[a.which||a.keyCode];b&&this.trigger(b+"Keyed",a)},_compareQueryToInputValue:function(){var a=this.getInputValue(),b=f(this.query,a),c=b?this.query.length!==a.length:!1;c?this.trigger("whitespaceChanged",{value:this.query}):b||this.trigger("queryChanged",{value:this.query=a})},destroy:function(){this.$hint.off(".tt"),this.$input.off(".tt"),this.$hint=this.$input=this.$overflowHelper=null},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){this.$input.val(a),!b&&this._compareQueryToInputValue()},getHintValue:function(){return this.$hint.val()},setHintValue:function(a){this.$hint.val(a)},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},isOverflow:function(){return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>this.$input.width()},isCursorAtEnd:function(){var a,b=this.$input.val().length,d=this.$input[0].selectionStart;return c.isNumber(d)?d===b:document.selection?(a=document.selection.createRange(),a.moveStart("character",-b),b===a.text.length):!0}}),b}(),k=function(){function b(b){c.bindAll(this),this.isOpen=!1,this.isEmpty=!0,this.isMouseOverDropdown=!1,this.$menu=a(b.menu).on("mouseenter.tt",this._handleMouseenter).on("mouseleave.tt",this._handleMouseleave).on("click.tt",".tt-suggestion",this._handleSelection).on("mouseover.tt",".tt-suggestion",this._handleMouseover)}function e(a){return a.data("suggestion")}var f={suggestionsList:'<span class="tt-suggestions"></span>'},g={suggestionsList:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"}};return c.mixin(b.prototype,d,{_handleMouseenter:function(){this.isMouseOverDropdown=!0},_handleMouseleave:function(){this.isMouseOverDropdown=!1},_handleMouseover:function(b){var c=a(b.currentTarget);this._getSuggestions().removeClass("tt-is-under-cursor"),c.addClass("tt-is-under-cursor")},_handleSelection:function(b){var c=a(b.currentTarget);this.trigger("suggestionSelected",e(c))},_show:function(){this.$menu.css("display","block")},_hide:function(){this.$menu.hide()},_moveCursor:function(a){var b,c,d,f;if(this.isVisible()){if(b=this._getSuggestions(),c=b.filter(".tt-is-under-cursor"),c.removeClass("tt-is-under-cursor"),d=b.index(c)+a,d=(d+1)%(b.length+1)-1,-1===d)return this.trigger("cursorRemoved"),void 0;-1>d&&(d=b.length-1),f=b.eq(d).addClass("tt-is-under-cursor"),this._ensureVisibility(f),this.trigger("cursorMoved",e(f))}},_getSuggestions:function(){return this.$menu.find(".tt-suggestions > .tt-suggestion")},_ensureVisibility:function(a){var b=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),c=this.$menu.scrollTop(),d=a.position().top,e=d+a.outerHeight(!0);0>d?this.$menu.scrollTop(c+d):e>b&&this.$menu.scrollTop(c+(e-b))},destroy:function(){this.$menu.off(".tt"),this.$menu=null},isVisible:function(){return this.isOpen&&!this.isEmpty},closeUnlessMouseIsOverDropdown:function(){this.isMouseOverDropdown||this.close()},close:function(){this.isOpen&&(this.isOpen=!1,this.isMouseOverDropdown=!1,this._hide(),this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor"),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(a){var b={left:"0",right:"auto"},c={left:"auto",right:" 0"};"ltr"===a?this.$menu.css(b):this.$menu.css(c)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getSuggestionUnderCursor:function(){var a=this._getSuggestions().filter(".tt-is-under-cursor").first();return a.length>0?e(a):null},getFirstSuggestion:function(){var a=this._getSuggestions().first();return a.length>0?e(a):null},renderSuggestions:function(b,d){var e,h,i,j,k,l="tt-dataset-"+b.name,m='<div class="tt-suggestion">%body</div>',n=this.$menu.find("."+l);0===n.length&&(h=a(f.suggestionsList).css(g.suggestionsList),n=a("<div></div>").addClass(l).append(b.header).append(h).append(b.footer).appendTo(this.$menu)),d.length>0?(this.isEmpty=!1,this.isOpen&&this._show(),i=document.createElement("div"),j=document.createDocumentFragment(),c.each(d,function(c,d){d.dataset=b.name,e=b.template(d.datum),i.innerHTML=m.replace("%body",e),k=a(i.firstChild).css(g.suggestion).data("suggestion",d),k.children().each(function(){a(this).css(g.suggestionChild)}),j.appendChild(k[0])}),n.show().find(".tt-suggestions").html(j)):this.clearSuggestions(b.name),this.trigger("suggestionsRendered")},clearSuggestions:function(a){var b=a?this.$menu.find(".tt-dataset-"+a):this.$menu.find('[class^="tt-dataset-"]'),c=b.find(".tt-suggestions");b.hide(),c.empty(),0===this._getSuggestions().length&&(this.isEmpty=!0,this._hide())}}),b}(),l=function(){function b(a){var b,d,f;c.bindAll(this),this.$node=e(a.input),this.datasets=a.datasets,this.dir=null,this.eventBus=a.eventBus,b=this.$node.find(".tt-dropdown-menu"),d=this.$node.find(".tt-query"),f=this.$node.find(".tt-hint"),this.dropdownView=new k({menu:b}).on("suggestionSelected",this._handleSelection).on("cursorMoved",this._clearHint).on("cursorMoved",this._setInputValueToSuggestionUnderCursor).on("cursorRemoved",this._setInputValueToQuery).on("cursorRemoved",this._updateHint).on("suggestionsRendered",this._updateHint).on("opened",this._updateHint).on("closed",this._clearHint).on("opened closed",this._propagateEvent),this.inputView=new j({input:d,hint:f}).on("focused",this._openDropdown).on("blured",this._closeDropdown).on("blured",this._setInputValueToQuery).on("enterKeyed tabKeyed",this._handleSelection).on("queryChanged",this._clearHint).on("queryChanged",this._clearSuggestions).on("queryChanged",this._getSuggestions).on("whitespaceChanged",this._updateHint).on("queryChanged whitespaceChanged",this._openDropdown).on("queryChanged whitespaceChanged",this._setLanguageDirection).on("escKeyed",this._closeDropdown).on("escKeyed",this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed",this._managePreventDefault).on("upKeyed downKeyed",this._moveDropdownCursor).on("upKeyed downKeyed",this._openDropdown).on("tabKeyed leftKeyed rightKeyed",this._autocomplete)}function e(b){var c=a(g.wrapper),d=a(g.dropdown),e=a(b),f=a(g.hint);c=c.css(h.wrapper),d=d.css(h.dropdown),f.css(h.hint).css({backgroundAttachment:e.css("background-attachment"),backgroundClip:e.css("background-clip"),backgroundColor:e.css("background-color"),backgroundImage:e.css("background-image"),backgroundOrigin:e.css("background-origin"),backgroundPosition:e.css("background-position"),backgroundRepeat:e.css("background-repeat"),backgroundSize:e.css("background-size")}),e.data("ttAttrs",{dir:e.attr("dir"),autocomplete:e.attr("autocomplete"),spellcheck:e.attr("spellcheck"),style:e.attr("style")}),e.addClass("tt-query").attr({autocomplete:"off",spellcheck:!1}).css(h.query);try{!e.attr("dir")&&e.attr("dir","auto")}catch(i){}return e.wrap(c).parent().prepend(f).append(d)}function f(a){var b=a.find(".tt-query");c.each(b.data("ttAttrs"),function(a,d){c.isUndefined(d)?b.removeAttr(a):b.attr(a,d)}),b.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter(a),a.remove()}var g={wrapper:'<span class="twitter-typeahead"></span>',hint:'<input class="tt-hint" type="text" autocomplete="off" spellcheck="off" disabled>',dropdown:'<span class="tt-dropdown-menu"></span>'},h={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none"},query:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"}};return c.isMsie()&&c.mixin(h.query,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),c.isMsie()&&c.isMsie()<=7&&(c.mixin(h.wrapper,{display:"inline",zoom:"1"}),c.mixin(h.query,{marginTop:"-1px"})),c.mixin(b.prototype,d,{_managePreventDefault:function(a){var b,c,d=a.data,e=!1;switch(a.type){case"tabKeyed":b=this.inputView.getHintValue(),c=this.inputView.getInputValue(),e=b&&b!==c;break;case"upKeyed":case"downKeyed":e=!d.shiftKey&&!d.ctrlKey&&!d.metaKey}e&&d.preventDefault()},_setLanguageDirection:function(){var a=this.inputView.getLanguageDirection();a!==this.dir&&(this.dir=a,this.$node.css("direction",a),this.dropdownView.setLanguageDirection(a))},_updateHint:function(){var a,b,d,e,f,g=this.dropdownView.getFirstSuggestion(),h=g?g.value:null,i=this.dropdownView.isVisible(),j=this.inputView.isOverflow();h&&i&&!j&&(a=this.inputView.getInputValue(),b=a.replace(/\s{2,}/g," ").replace(/^\s+/g,""),d=c.escapeRegExChars(b),e=new RegExp("^(?:"+d+")(.*$)","i"),f=e.exec(h),this.inputView.setHintValue(a+(f?f[1]:"")))},_clearHint:function(){this.inputView.setHintValue("")},_clearSuggestions:function(){this.dropdownView.clearSuggestions()},_setInputValueToQuery:function(){this.inputView.setInputValue(this.inputView.getQuery())},_setInputValueToSuggestionUnderCursor:function(a){var b=a.data;this.inputView.setInputValue(b.value,!0)},_openDropdown:function(){this.dropdownView.open()},_closeDropdown:function(a){this.dropdownView["blured"===a.type?"closeUnlessMouseIsOverDropdown":"close"]()},_moveDropdownCursor:function(a){var b=a.data;b.shiftKey||b.ctrlKey||b.metaKey||this.dropdownView["upKeyed"===a.type?"moveCursorUp":"moveCursorDown"]()},_handleSelection:function(a){var b="suggestionSelected"===a.type,d=b?a.data:this.dropdownView.getSuggestionUnderCursor();d&&(this.inputView.setInputValue(d.value),b?this.inputView.focus():a.data.preventDefault(),b&&c.isMsie()?c.defer(this.dropdownView.close):this.dropdownView.close(),this.eventBus.trigger("selected",d.datum,d.dataset))},_getSuggestions:function(){var a=this,b=this.inputView.getQuery();c.isBlankString(b)||c.each(this.datasets,function(c,d){d.getSuggestions(b,function(c){b===a.inputView.getQuery()&&a.dropdownView.renderSuggestions(d,c)})})},_autocomplete:function(a){var b,c,d,e,f;("rightKeyed"!==a.type&&"leftKeyed"!==a.type||(b=this.inputView.isCursorAtEnd(),c="ltr"===this.inputView.getLanguageDirection()?"leftKeyed"===a.type:"rightKeyed"===a.type,b&&!c))&&(d=this.inputView.getQuery(),e=this.inputView.getHintValue(),""!==e&&d!==e&&(f=this.dropdownView.getFirstSuggestion(),this.inputView.setInputValue(f.value),this.eventBus.trigger("autocompleted",f.datum,f.dataset)))},_propagateEvent:function(a){this.eventBus.trigger(a.type)},destroy:function(){this.inputView.destroy(),this.dropdownView.destroy(),f(this.$node),this.$node=null},setQuery:function(a){this.inputView.setQuery(a),this.inputView.setInputValue(a),this._clearHint(),this._clearSuggestions(),this._getSuggestions()}}),b}();!function(){var b,d={},f="ttView";b={initialize:function(b){function g(){var b,d=a(this),g=new e({el:d});b=c.map(h,function(a){return a.initialize()}),d.data(f,new l({input:d,eventBus:g=new e({el:d}),datasets:h})),a.when.apply(a,b).always(function(){c.defer(function(){g.trigger("initialized")})})}var h;return b=c.isArray(b)?b:[b],0===b.length&&a.error("no datasets provided"),h=c.map(b,function(a){var b=d[a.name]?d[a.name]:new i(a);return a.name&&(d[a.name]=b),b}),this.each(g)},destroy:function(){function b(){var b=a(this),c=b.data(f);c&&(c.destroy(),b.removeData(f))}return this.each(b)},setQuery:function(b){function c(){var c=a(this).data(f);c&&c.setQuery(b)}return this.each(c)}},jQuery.fn.typeahead=function(a){return b[a]?b[a].apply(this,[].slice.call(arguments,1)):b.initialize.apply(this,arguments)}}()}(window.jQuery); \ No newline at end of file