Commit 38813f12 authored by Ian Dennis Miller's avatar Ian Dennis Miller

split js further, add colors to identicons, favicon for page, keywords widget, keyword search

parent ea0dd615
......@@ -14,9 +14,9 @@ requirements:
test:
mkdir -p ./build
DEBUGVISFACT=T bin/visfact-scaffold-config.py build/config.yaml
DEBUGVISFACT=T bin/visfact-scaffold-article.py build/article.ttl
DEBUGVISFACT=T bin/visfact-make.py build/config.yaml
# DEBUGVISFACT=T bin/visfact-scaffold-config.py build/config.yaml
# DEBUGVISFACT=T bin/visfact-scaffold-article.py build/article.ttl
# DEBUGVISFACT=T bin/visfact-make.py build/config.yaml
DEBUGVISFACT=T bin/visfact-make.py example/visfact.yaml
snippets-sublime-text-3:
......
var toggle_article = function(id) {
// find the article button
var button = document.getElementById(id + "-button");
hide_picker();
// if cards are not filtered
if (! filtered) {
filtered = true;
filter_id = id;
// hide all
for (var i = 0; i < divs.length; i++){
divs[i].style.display = "none";
}
// show just this article
var els = document.querySelectorAll('[about="#' + id + '"]');
for (var i = 0; i < els.length; i++){
els[i].style.display = "block";
}
button.classList.add('filtered');
close_ui();
}
else {
filtered = false;
button.classList.remove('filtered');
show_all();
}
}
var hide_picker = function() {
var els = document.querySelectorAll('#article-list');
els[0].style.display = "none";
close_ui();
}
var show_picker = function() {
var els = document.querySelectorAll('#article-list');
els[0].style.display = "block";
hide_keywords();
open_ui();
}
var toggle_picker = function() {
var els = document.querySelectorAll('#article-list');
if (els[0].style.display == "block") {
hide_picker();
}
else {
show_picker();
}
}
......@@ -14,6 +14,12 @@ var handler = function(e) {
e.stopPropagation();
toggle_picker();
}
else if (e.ctrlKey && charCode == '75') {
// k: keywords
e.preventDefault();
e.stopPropagation();
toggle_keywords();
}
else if (e.ctrlKey && charCode == '90') {
// z: zoom
e.preventDefault();
......
var hide_keywords = function() {
var els = document.querySelectorAll('#keyword-list');
els[0].style.display = "none";
close_ui();
}
var show_keywords = function() {
var els = document.querySelectorAll('#keyword-list');
els[0].style.display = "block";
hide_picker();
open_ui();
}
var toggle_keywords = function() {
var els = document.querySelectorAll('#keyword-list');
if (els[0].style.display == "block") {
hide_keywords();
}
else {
show_keywords();
}
}
var keyword_search = function(words) {
hide_keywords();
close_ui();
var terms = words.split(" ");
var matches = do_search(terms);
show_results(terms, matches);
}
......@@ -99,38 +99,6 @@ var show_previous = function() {
refresh(els);
}
/* filter by article */
var toggle_article = function(id) {
// find the article button
var button = document.getElementById(id + "-button");
// if cards are not filtered
if (! filtered) {
filtered = true;
filter_id = id;
// hide all
for (var i = 0; i < divs.length; i++){
divs[i].style.display = "none";
}
// show just this article
var els = document.querySelectorAll('[about="#' + id + '"]');
for (var i = 0; i < els.length; i++){
els[i].style.display = "block";
}
button.classList.add('filtered');
close_ui();
}
else {
filtered = false;
button.classList.remove('filtered');
show_all();
}
}
/* Appearance */
var toggle_appearance = function(id) {
......@@ -169,73 +137,6 @@ var toggle_appearances = function() {
}
}
/* UI */
var close_ui = function() {
var content = document.getElementById("ui-content");
var ui_control = document.getElementById("ui-control");
var ui_elem = document.getElementById("ui");
hide_search();
content.style.display = "none";
ui_control.classList.remove('expanded');
ui_elem.classList.remove('expanded');
// ensure help is closed
var el = document.getElementById("ui-help");
if (el.classList.contains("expanded")) {
el.classList.remove('expanded');
}
}
var open_ui = function() {
var content = document.getElementById("ui-content");
var ui_control = document.getElementById("ui-control");
var ui_elem = document.getElementById("ui");
content.style.display = "block";
ui_control.classList.add('expanded');
ui_elem.classList.add('expanded');
}
var toggle_ui = function() {
var content = document.getElementById("ui-content");
var search = document.getElementById("ui-search");
if (content.style.display != "none" || search.style.display != "none") {
close_ui();
hide_picker();
}
else {
open_ui();
}
}
/* picker */
var hide_picker = function() {
var els = document.querySelectorAll('#article-list');
els[0].style.display = "none";
close_ui();
}
var show_picker = function() {
var els = document.querySelectorAll('#article-list');
els[0].style.display = "block";
open_ui();
}
var toggle_picker = function() {
var els = document.querySelectorAll('#article-list');
if (els[0].style.display == "block") {
hide_picker();
}
else {
show_picker();
}
}
/* help */
var toggle_help = function() {
......
......@@ -44,9 +44,8 @@ var init_search = function() {
}
var new_search = function() {
terms_raw = document.querySelector("#ui-query").value;
if (terms_raw != "") {
var terms = terms_raw.split(" ");
var terms = get_terms();
if (terms.length > 0) {
var matches = do_search(terms);
show_results(terms, matches);
hide_search();
......@@ -56,6 +55,15 @@ var new_search = function() {
}
}
var get_terms = function() {
var terms_raw = document.querySelector("#ui-query").value;
var terms = [];
if (terms_raw != "") {
terms = terms_raw.split(" ");
}
return(terms);
}
var do_search = function(terms) {
var matches = {};
......
var close_ui = function() {
var content = document.getElementById("ui-content");
var ui_control = document.getElementById("ui-control");
var ui_elem = document.getElementById("ui");
hide_search();
content.style.display = "none";
ui_control.classList.remove('expanded');
ui_elem.classList.remove('expanded');
// ensure help is closed
var el = document.getElementById("ui-help");
if (el.classList.contains("expanded")) {
el.classList.remove('expanded');
}
}
var open_ui = function() {
var content = document.getElementById("ui-content");
var ui_control = document.getElementById("ui-control");
var ui_elem = document.getElementById("ui");
content.style.display = "block";
ui_control.classList.add('expanded');
ui_elem.classList.add('expanded');
}
var toggle_ui = function() {
var content = document.getElementById("ui-content");
var search = document.getElementById("ui-search");
if (content.style.display != "none" || search.style.display != "none") {
close_ui();
hide_picker();
}
else {
open_ui();
}
}
......@@ -7,13 +7,14 @@
xmlns:thesis="https://projects.sisrlab.com/idm/visfact/raw/master/schema/thesis.rdf#"
version="XHTML+RDFa 1.0" xml:lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#333">
<meta name="msapplication-navbutton-color" content="#333">
<meta name="apple-mobile-web-app-status-bar-style" content="#333">
<style type="text/css">
{% include 'style.css' %}
</style>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#333">
<meta name="msapplication-navbutton-color" content="#333">
<meta name="apple-mobile-web-app-status-bar-style" content="#333">
<link rel="shortcut icon" type="image/png" href="data:image/png;base64,{{ favicon }}">
<style type="text/css">
{% include 'style.css' %}
</style>
</head>
<body class="dark">
<div id="container">
......@@ -32,9 +33,16 @@
{% endfor %}
</ul>
<ul id="keyword-list">
{% for words in keywords %}
<li><a href="#" onclick="keyword_search('{{ words }}'); return false;">{{ words }}</a></li>
{% endfor %}
</ul>
<ul id="ui-config">
<li><a href="#" onclick="toggle_picker(); return false;">articles</a></li>
<li><a href="#" onclick="toggle_search(); return false;">search</a></li>
<li><a href="#" onclick="toggle_keywords(); return false;">keywords</a></li>
<li><a href="#" onclick="toggle_focus(); return false;">zoom to card</a></li>
<li><a href="#" onclick="toggle_appearances(); return false;">titles</a></li>
<li><a href="#" onclick="toggle_dark_mode(); return false;">night mode</a></li>
......@@ -48,6 +56,7 @@
<li><b>ESC</b>: show/hide UI control</li>
<li><b>ctrl-a</b>: article picker</li>
<li><b>ctrl-s</b>: search</li>
<li><b>ctrl-k</b>: keywords</li>
<li><b>ctrl-z</b>: zoom cards</li>
<li><b>left/right</b>: previous/next (while zoomed)</li>
<li><b>ctrl-h</b>: show/hide help</li>
......@@ -61,8 +70,11 @@
</div>
<script>
var keywords = {{ keywords }};
var keywords = {{ keywords_json }};
{% include 'js/swiper.js' %}
{% include 'js/ui.js' %}
{% include 'js/articles.js' %}
{% include 'js/keywords.js' %}
{% include 'js/pager.js' %}
{% include 'js/search.js' %}
{% include 'js/keyboard.js' %}
......
......@@ -60,7 +60,6 @@ ul {
.appearance {
font-style: italic;
display: none;
font-size: 10pt;
margin-top: 0;
margin-bottom: 0.5em;
......@@ -145,11 +144,11 @@ a#ui-control {
transform: rotate(90deg);
}
#article-list {
#article-list, #keyword-list {
display: none;
}
#ui ul#article-list li {
#ui ul#article-list li, #ui ul#keyword-list li{
border: 1px solid #999;
padding: 0.3em;
border-radius: 5px;
......@@ -158,7 +157,7 @@ a#ui-control {
background: #eee;
}
#ui ul#article-list {
#ui ul#article-list, #ui ul#keyword-list {
max-height: 15em;
overflow-y: scroll;
}
......
......@@ -11,7 +11,6 @@ import hashlib
import urllib.parse
from pydenticon import Generator
from jinja2 import Environment, PackageLoader, select_autoescape
from nltk.collocations import BigramCollocationFinder
from .__meta__ import __version__
......@@ -41,9 +40,12 @@ class VisFact:
self.g = rdflib.ConjunctiveGraph()
self.quote_identicon_generator = Generator(rows=8, columns=8, digest=hashlib.sha512)
self.favicon_generator = Generator(rows=12, columns=12, digest=hashlib.sha512,
foreground=["#000000"], background="#ffffff")
self.quote_identicon_generator = Generator(rows=8, columns=8, digest=hashlib.sha512,
foreground=["#333300", "#660066", "#009999"], background="#ffffff")
self.source_identicon_generator = Generator(rows=8, columns=8, digest=hashlib.sha512,
background="#999999")
foreground=["#bbbb66", "#bb66bb", "#66bbbb"], background="#000000")
def load_config(self, yaml_file):
with open(yaml_file, "r") as f:
......@@ -73,8 +75,6 @@ class VisFact:
if m:
fact_id = "claim-{0:0>2}-{1:0>4}".format(m.group(1), m.group(2))
content += quote + ' '
cite = "{authors}. ({year}). {title}.".format(
authors=authors,
year=year,
......@@ -87,18 +87,12 @@ class VisFact:
title=appearance_title
)
quote_identicon_data = self.quote_identicon_generator.generate(
data=alpha_pattern.sub('', quote.upper()), width=16, height=16)
appearance_identicon_data = self.source_identicon_generator.generate(
data=alpha_pattern.sub('', appearance_cite.upper()), width=16, height=16)
source_identicon_data = self.source_identicon_generator.generate(
data=alpha_pattern.sub('', cite.upper()), width=16, height=16)
if appearance_id not in articles.keys():
articles[appearance_id] = appearance_cite
# prepare the source citation
source_identicon_data = self.source_identicon_generator.generate(
data=alpha_pattern.sub('', cite.upper()), width=16, height=16)
source = {
'authors': authors,
'year': year,
......@@ -108,7 +102,16 @@ class VisFact:
'query': urllib.parse.quote_plus(', '.join([authors, year, title])),
}
# if this fact has not been added yet
if fact_id not in facts.keys():
quote_identicon_data = self.quote_identicon_generator.generate(
data=alpha_pattern.sub('', quote.upper()), width=16, height=16)
appearance_identicon_data = self.source_identicon_generator.generate(
data=alpha_pattern.sub('', appearance_cite.upper()), width=16, height=16)
content += quote + '\n'
facts[fact_id] = {
'id': "{0}".format(fact_id),
'quote': quote,
......@@ -120,6 +123,7 @@ class VisFact:
'appearance_identicon': base64.b64encode(appearance_identicon_data).decode(),
'sources': [source],
}
# otherwise, append source to existing fact
else:
facts[fact_id]['sources'].append(source)
......@@ -131,14 +135,18 @@ class VisFact:
def find_keywords(self, content):
bigram_measures = nltk.collocations.BigramAssocMeasures()
tokens = nltk.word_tokenize(content)
measure = bigram_measures.likelihood_ratio
# measure = bigram_measures.pmi
ignored_words = nltk.corpus.stopwords.words('english')
finder = BigramCollocationFinder.from_words(tokens)
finder.apply_word_filter(lambda w: len(w) < 3 or w.lower() in ignored_words)
finder.apply_freq_filter(2)
res = finder.nbest(bigram_measures.pmi, 10)
return([' '.join(item) for item in res])
tokens = nltk.word_tokenize(content)
finder = nltk.collocations.BigramCollocationFinder.from_words(tokens, window_size=5)
finder.apply_word_filter(lambda w: len(w) < 3 or w.lower() in ignored_words or w.isdigit())
finder.apply_freq_filter(5)
res = finder.nbest(measure, 20)
res_list = [' '.join(item) for item in res]
return(res_list)
def write_html(self):
if "rdf" in self.cfg.keys():
......@@ -154,15 +162,20 @@ class VisFact:
sorted_articles = sorted(articles.items(), key=lambda x: x[1])
keywords = self.find_keywords(content)
print(keywords)
# favicon
favicon_data = self.favicon_generator.generate(
data=self.cfg["dest"], width=48, height=48)
html_tmpl = self.env.get_template('main.html.j2')
with open(self.cfg["dest"], "wb") as f:
buf = html_tmpl.render(
quotes=result,
keywords=json.dumps(keywords),
keywords=keywords,
keywords_json=json.dumps(keywords),
articles=sorted_articles,
version=__version__
version=__version__,
favicon=base64.b64encode(favicon_data).decode(),
)
buf = re.sub(r'file:///.+?#', '', buf)
f.write(buf.encode())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment