Selaa lähdekoodia

Merge branch 'feature/style' into develop

New commits in `feature/style` address various issues.
tags/v1.0^2
Severyn Kozak 10 vuotta sitten
vanhempi
commit
06012910b7
13 muutettua tiedostoa jossa 635 lisäystä ja 177 poistoa
  1. +1
    -1
      .gitignore
  2. +1
    -1
      app.py
  3. +1
    -1
      bitshift/languages.py
  4. +65
    -0
      static/css/lib/github.css
  5. +64
    -0
      static/css/lib/highlight.css
  6. +13
    -8
      static/js/index.advanced-search-form.js
  7. +266
    -53
      static/js/index.js
  8. +0
    -7
      static/js/lib/typeahead.bundle.min.js
  9. +5
    -0
      static/sass/_mixins.sass
  10. +157
    -101
      static/sass/index.sass
  11. +14
    -3
      templates/index.html
  12. +8
    -2
      templates/layout.html
  13. +40
    -0
      test/resources/app.py

+ 1
- 1
.gitignore Näytä tiedosto

@@ -1,5 +1,5 @@
static/css/*
!static/css/lib/*
!lib

*.swp
.sass-cache


+ 1
- 1
app.py Näytä tiedosto

@@ -22,7 +22,7 @@ database = Database()

@app.route("/")
def index():
return render_template("index.html", typeahead_languages=LANGS)
return render_template("index.html", autocomplete_languages=LANGS)

@app.route("/search.json")
def search():


+ 1
- 1
bitshift/languages.py Näytä tiedosto

@@ -2,4 +2,4 @@ import json
from os import path

with open(path.join(path.dirname(__file__), "languages.json")) as lang_json:
LANGS = [lang for lang in json.load(lang_json)["languages"]]
LANGS = [lang.encode("utf8") for lang in json.load(lang_json)["languages"]]

+ 65
- 0
static/css/lib/github.css Näytä tiedosto

@@ -0,0 +1,65 @@
td.linenos { background: rgba(65,131,196,0.05); padding-right: 10px; border-right: 1px solid #bbb; }
span.lineno { background: rgba(65,131,196,0.05); padding: 0 5px 0 5px; }
pre { line-height: 125% }
.highlighttable { background-color: #fff; padding-left: 10px; width: inherit; height: inherit; }
.hll { display: block }
.c { color: #999988; font-style: italic } /* Comment */
.err { color: #a61717; background-color: #e3d2d2 } /* Error */
.k { color: #000000; font-weight: bold } /* Keyword */
.o { color: #000000; font-weight: bold } /* Operator */
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
.c1 { color: #999988; font-style: italic } /* Comment.Single */
.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.ge { color: #000000; font-style: italic } /* Generic.Emph */
.gr { color: #aa0000 } /* Generic.Error */
.gh { color: #999999 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #888888 } /* Generic.Output */
.gp { color: #555555 } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #aaaaaa } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc { color: #000000; font-weight: bold } /* Keyword.Constant */
.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
.m { color: #009999 } /* Literal.Number */
.s { color: #d01040 } /* Literal.String */
.na { color: #008080 } /* Name.Attribute */
.nb { color: #0086B3 } /* Name.Builtin */
.nc { color: #445588; font-weight: bold } /* Name.Class */
.no { color: #008080 } /* Name.Constant */
.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
.ni { color: #800080 } /* Name.Entity */
.ne { color: #990000; font-weight: bold } /* Name.Exception */
.nf { color: #990000; font-weight: bold } /* Name.Function */
.nl { color: #990000; font-weight: bold } /* Name.Label */
.nn { color: #555555 } /* Name.Namespace */
.nt { color: #000080 } /* Name.Tag */
.nv { color: #008080 } /* Name.Variable */
.ow { color: #000000; font-weight: bold } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #009999 } /* Literal.Number.Float */
.mh { color: #009999 } /* Literal.Number.Hex */
.mi { color: #009999 } /* Literal.Number.Integer */
.mo { color: #009999 } /* Literal.Number.Oct */
.sb { color: #d01040 } /* Literal.String.Backtick */
.sc { color: #d01040 } /* Literal.String.Char */
.sd { color: #d01040 } /* Literal.String.Doc */
.s2 { color: #d01040 } /* Literal.String.Double */
.se { color: #d01040 } /* Literal.String.Escape */
.sh { color: #d01040 } /* Literal.String.Heredoc */
.si { color: #d01040 } /* Literal.String.Interpol */
.sx { color: #d01040 } /* Literal.String.Other */
.sr { color: #009926 } /* Literal.String.Regex */
.s1 { color: #d01040 } /* Literal.String.Single */
.ss { color: #990073 } /* Literal.String.Symbol */
.bp { color: #999999 } /* Name.Builtin.Pseudo */
.vc { color: #008080 } /* Name.Variable.Class */
.vg { color: #008080 } /* Name.Variable.Global */
.vi { color: #008080 } /* Name.Variable.Instance */
.il { color: #009999 } /* Literal.Number.Integer.Long */

+ 64
- 0
static/css/lib/highlight.css Näytä tiedosto

@@ -0,0 +1,64 @@
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
pre { line-height: 125% }
.highlighttable { background-color: #49483e; width: inherit; height: inherit; }
.hll { display: block }
{ background: #272822; color: #f8f8f2 }
.c { color: #75715e } /* Comment */
.err { color: #960050; background-color: #1e0010 } /* Error */
.k { color: #66d9ef } /* Keyword */
.l { color: #ae81ff } /* Literal */
.n { color: #f8f8f2 } /* Name */
.o { color: #f92672 } /* Operator */
.p { color: #f8f8f2 } /* Punctuation */
.cm { color: #75715e } /* Comment.Multiline */
.cp { color: #75715e } /* Comment.Preproc */
.c1 { color: #75715e } /* Comment.Single */
.cs { color: #75715e } /* Comment.Special */
.ge { font-style: italic } /* Generic.Emph */
.gs { font-weight: bold } /* Generic.Strong */
.kc { color: #66d9ef } /* Keyword.Constant */
.kd { color: #66d9ef } /* Keyword.Declaration */
.kn { color: #f92672 } /* Keyword.Namespace */
.kp { color: #66d9ef } /* Keyword.Pseudo */
.kr { color: #66d9ef } /* Keyword.Reserved */
.kt { color: #66d9ef } /* Keyword.Type */
.ld { color: #e6db74 } /* Literal.Date */
.m { color: #ae81ff } /* Literal.Number */
.s { color: #e6db74 } /* Literal.String */
.na { color: #a6e22e } /* Name.Attribute */
.nb { color: #f8f8f2 } /* Name.Builtin */
.nc { color: #a6e22e } /* Name.Class */
.no { color: #66d9ef } /* Name.Constant */
.nd { color: #a6e22e } /* Name.Decorator */
.ni { color: #f8f8f2 } /* Name.Entity */
.ne { color: #a6e22e } /* Name.Exception */
.nf { color: #a6e22e } /* Name.Function */
.nl { color: #f8f8f2 } /* Name.Label */
.nn { color: #f8f8f2 } /* Name.Namespace */
.nx { color: #a6e22e } /* Name.Other */
.py { color: #f8f8f2 } /* Name.Property */
.nt { color: #f92672 } /* Name.Tag */
.nv { color: #f8f8f2 } /* Name.Variable */
.ow { color: #f92672 } /* Operator.Word */
.w { color: #f8f8f2 } /* Text.Whitespace */
.mf { color: #ae81ff } /* Literal.Number.Float */
.mh { color: #ae81ff } /* Literal.Number.Hex */
.mi { color: #ae81ff } /* Literal.Number.Integer */
.mo { color: #ae81ff } /* Literal.Number.Oct */
.sb { color: #e6db74 } /* Literal.String.Backtick */
.sc { color: #e6db74 } /* Literal.String.Char */
.sd { color: #e6db74 } /* Literal.String.Doc */
.s2 { color: #e6db74 } /* Literal.String.Double */
.se { color: #ae81ff } /* Literal.String.Escape */
.sh { color: #e6db74 } /* Literal.String.Heredoc */
.si { color: #e6db74 } /* Literal.String.Interpol */
.sx { color: #e6db74 } /* Literal.String.Other */
.sr { color: #e6db74 } /* Literal.String.Regex */
.s1 { color: #e6db74 } /* Literal.String.Single */
.ss { color: #e6db74 } /* Literal.String.Symbol */
.bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.vc { color: #f8f8f2 } /* Name.Variable.Class */
.vg { color: #f8f8f2 } /* Name.Variable.Global */
.vi { color: #f8f8f2 } /* Name.Variable.Instance */
.il { color: #ae81ff } /* Literal.Number.Integer.Long */

+ 13
- 8
static/js/index.advanced-search-form.js Näytä tiedosto

@@ -37,6 +37,8 @@ var searchGroups = $("div#search-groups");
searchGroups.append(
searchGroup.append(createSearchGroupInput("language")));
$("div#sidebar input[type=checkbox]#language").prop("checked", true);

searchGroups[0].scrollTop = searchGroups[0].scrollHeight;
});

// Remove the currently selected group if it's not the only one, and mark
@@ -67,7 +69,7 @@ var searchGroups = $("div#search-groups");
})
});

// Add an input field to the currently selected search group.
// Toggle the presence of an input field.
$("div#sidebar input[type=checkbox]").click(function(){
var fieldId = $(this).prop("id");
if($(this).is(":checked")){
@@ -76,8 +78,13 @@ var searchGroups = $("div#search-groups");
if(fieldId.slice(0, 4) == "date")
$(".search-group#selected ." + fieldId).datepicker();
}
else
$("div.search-group#selected #" + fieldId).remove()
else {
if($(".search-group#selected").children("div").length > 1)
$(".search-group#selected #" + fieldId).remove()
else
$(this).prop("checked", true);
}
searchGroups[0].scrollTop = searchGroups[0].scrollHeight;
});

var previousAdvancedQuery = "";
@@ -125,7 +132,8 @@ function assembleQuery(){
groupQuery.push(genFieldQueryString(
inputFields[field], regexCheckbox[field].checked));

groupQueries.push(groupQuery.join(" AND "));
if(groupQuery.length > 0)
groupQueries.push(groupQuery.join(" AND "));
}

return groupQueries.join(" OR ");
@@ -140,8 +148,5 @@ function assembleQuery(){
function genFieldQueryString(field, hasRegex){
var terms = field.value.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
var query = field.getAttribute("name") + ":" + (hasRegex?"re:":"") + terms;
if(field.value.indexOf('"') >= 0){
return '"' + query + '"';
}
return query;
return '"' + query + '"';
}

+ 266
- 53
static/js/index.js Näytä tiedosto

@@ -5,34 +5,145 @@

var advancedSearchDiv = $("div#advanced-search");
var advancedSearchButton = $("button#advanced-search");
advancedSearchButton.click(function(){
var searchField = $("div#search-field");
if(!advancedSearchDiv.hasClass("visible")){
searchField.addClass("partly-visible");
advancedSearchDiv.fadeIn(500).addClass("visible");
advancedSearchButton.addClass("clicked");
}
else {
advancedSearchDiv.fadeOut(300).removeClass("visible");
advancedSearchButton.removeClass("clicked");
if($("div#results .result").length == 0)
searchField.removeClass("partly-visible");
FINISH_TYPING_INTERVAL = 650;
var searchBar = $("form#search-bar input[type='text']")[0];
var resultsDiv = $("div#results")[0];

var typingTimer, scrollTimer, lastValue;
var searchResultsPage = 1;

/*
* Set all page callbacks.
*/
(function setHomePageCallbabacks(){
var results = $('#results').get(0);

// Enable infinite scrolling down the results page.
$(window).scroll(function(){
if($(window).scrollTop() + $(window).height() == $(document).height() &&
resultsDiv.querySelectorAll(".result").length > 0)
loadMoreResults();

clearTimeout(scrollTimer);
if (!results.classList.contains('disable-hover'))
results.classList.add('disable-hover')

scrollTimer = setTimeout(function(){
if (results.classList.contains('disable-hover'))
results.classList.remove('disable-hover');
}, 200);
});

// Toggle the advanced-search form's visibility.
advancedSearchButton.click(function(){
var searchField = $("div#search-field");
if(!advancedSearchDiv.hasClass("visible")){
searchField.addClass("partly-visible");
advancedSearchDiv.fadeIn(500).addClass("visible");
advancedSearchButton.addClass("clicked");
}
else {
advancedSearchDiv.fadeOut(300).removeClass("visible");
advancedSearchButton.removeClass("clicked");
if($("div#results .result").length == 0)
searchField.removeClass("partly-visible");
}
});

// Enable capturing the `enter` key.
$("form#search-bar").submit(function(event){
event.preventDefault();
return false;
});
searchBar.onkeyup = typingTimer;
}());

/*
* Set keyboard shortcut mappings.
*/
(function resultsHotkeys(){
/*
* If the currently viewed result is not the first, scroll to the previous
* result.
*/
var previousResult = function(){
var currResult = $(".display-all");
if(currResult.length) {
currResult.removeClass("display-all");
currResult = currResult.closest(".result").prev(".result");
} else {
currResult = $(document.querySelectorAll(".result")[0]);
}

currResult.addClass("display-all");
currResult.each(function(){
$('html,body').stop().animate({
scrollTop: $(this).offset().top - (
$(window).height() - $(this).outerHeight(true)) / 2
}, 140);
});
};

/*
* If the currently viewed result is not the last, scroll to the next
* result.
*/
var nextResult = function(){
var currResult = $(".display-all");
if(currResult.length) {
currResult.removeClass("display-all");
currResult = currResult.closest(".result").next(".result");
} else {
currResult = $(document.querySelectorAll(".result")[0]);
}

currResult.addClass('display-all');
currResult.each(function(){
$('html,body').stop().animate({
scrollTop: $(this).offset().top - (
$(window).height() - $(this).outerHeight(true)) / 2
}, 140);
});
};

var displayHotkeyHelp = function(){
var help = $("div#hotkey-help");
console.log("H");
if(help.hasClass("hidden"))
help.fadeIn(420);
else
help.fadeOut(420);

$("div#body").toggleClass("faded");
help.toggleClass("hidden");
}
});

FINISH_TYPING_INTERVAL = 650;
searchBar = $("form#search-bar input[type='text']")[0];
resultsDiv = $("div#results")[0];
var hotkeyActions = {
"k" : previousResult,
"j" : nextResult,
"h" : previousSymbolMatch,
"l" : nextSymbolMatch,
"?" : displayHotkeyHelp
};

$(window).keypress(function(key){
for(var hotkey in hotkeyActions){
var keyChar = String.fromCharCode(key.keyCode);
if(keyChar == hotkey &&
!($(key.target).is("textarea") || $(key.target).is("input")))
hotkeyActions[keyChar]();
}
});
}());

var typingTimer, lastValue;
//Obtained by parsing python file with pygments
var codeExample = '<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40</pre></div></td><td class="code"><div class="hll"><pre><span class="sd">&quot;&quot;&quot;</span>\n<span class="sd">Module to contain all the project&#39;s Flask server plumbing.</span>\n<span class="sd">&quot;&quot;&quot;</span>\n\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">session</span>\n\n<span class="kn">from</span> <span class="nn">bitshift</span> <span class="kn">import</span> <span class="n">assets</span>\n<span class="c"># from bitshift.database import Database</span>\n<span class="c"># from bitshift.query import parse_query</span>\n\n<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>\n<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_object</span><span class="p">(</span><span class="s">&quot;bitshift.config&quot;</span><span class="p">)</span>\n\n<span class="n">app_env</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">jinja_env</span>\n<span class="n">app_env</span><span class="o">.</span><span class="n">line_statement_prefix</span> <span class="o">=</span> <span class="s">&quot;=&quot;</span>\n<span class="n">app_env</span><span class="o">.</span><span class="n">globals</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">assets</span><span class="o">=</span><span class="n">assets</span><span class="p">)</span>\n\n<span class="c"># database = Database()</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;index.html&quot;</span><span class="p">)</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/search/&lt;query&gt;&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="n">query</span><span class="p">):</span>\n <span class="c"># tree = parse_query(query)</span>\n <span class="c"># database.search(tree)</span>\n <span class="k">pass</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/about&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">about</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;about.html&quot;</span><span class="p">)</span>\n\n<span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/developers&quot;</span><span class="p">)</span>\n<span class="k">def</span> <span class="nf">developers</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;developers.html&quot;</span><span class="p">)</span>\n\n<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>\n <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>\n</pre></div>\n</td></tr></table>'
var codeExample = '<table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre> 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40</pre></div></td><td class="code"><div class="highlight"><pre><span class="sd">&quot;&quot;&quot;</span>\n<span class="sd">Module to contain all the project&#39;s Flask server plumbing.</span>\n<span class="sd">&quot;&quot;&quot;</span>\n\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span>\n<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">session</span>\n\n<span class="kn">from</span> <span class="nn">bitshift</span> <span class="kn">import</span> <span class="n">assets</span>\n<span class="c"># from bitshift.database import Database</span>\n<span class="c"># from bitshift.query import parse_query</span>\n\n<span class="hll"><span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>\n</span><span class="hll"><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_object</span><span class="p">(</span><span class="s">&quot;bitshift.config&quot;</span><span class="p">)</span>\n</span>\n<span class="hll"><span class="n">app_env</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">jinja_env</span>\n</span><span class="hll"><span class="n">app_env</span><span class="o">.</span><span class="n">line_statement_prefix</span> <span class="o">=</span> <span class="s">&quot;=&quot;</span>\n</span><span class="hll"><span class="n">app_env</span><span class="o">.</span><span class="n">globals</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">assets</span><span class="o">=</span><span class="n">assets</span><span class="p">)</span>\n</span>\n<span class="c"># database = Database()</span>\n\n<span class="hll"><span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">)</span>\n</span><span class="k">def</span> <span class="nf">index</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;index.html&quot;</span><span class="p">)</span>\n\n<span class="hll"><span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/search/&lt;query&gt;&quot;</span><span class="p">)</span>\n</span><span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="n">query</span><span class="p">):</span>\n <span class="c"># tree = parse_query(query)</span>\n <span class="c"># database.search(tree)</span>\n <span class="k">pass</span>\n\n<span class="hll"><span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/about&quot;</span><span class="p">)</span>\n</span><span class="k">def</span> <span class="nf">about</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;about.html&quot;</span><span class="p">)</span>\n\n<span class="hll"><span class="nd">@app.route</span><span class="p">(</span><span class="s">&quot;/developers&quot;</span><span class="p">)</span>\n</span><span class="k">def</span> <span class="nf">developers</span><span class="p">():</span>\n <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">&quot;developers.html&quot;</span><span class="p">)</span>\n\n<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>\n<span class="hll"> <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>\n</span></pre></div>\n</td></tr></table>'
searchBar.onkeyup = typingTimer;

var testCodelet = {
'url': 'https://github.com/earwig/bitshift/blob/develop/app.py',
'filename': 'app.py',
'language': 'Python',
'language': 'python',
'date_created': 'May 10, 2014',
'date_modified': '2 days ago',
'origin': ['GitHub', 'https://github.com', ''],
@@ -43,17 +154,12 @@ var testCodelet = {
// Enable infinite scrolling down the results page.
$(window).scroll(function() {
var searchField = $("div#search-field");
if($(window).scrollTop() + $(window).height() == $(document).height() && searchField.hasClass('partly-visible')){
if($(window).scrollTop() + $(window).height() == $(document).height() &&
searchField.hasClass('partly-visible')){
loadMoreResults();
}
});

// Enable capturing the `enter` key.
$("form#search-bar").submit(function(event){
event.preventDefault();
return false;
});

/*
* Clear the existing timer and set a new one the the user types text into the
* search bar.
@@ -109,6 +215,7 @@ function clearResults(){
* with its response.
*/
function populateResults(){
searchResultsPage = 1;
var results = queryServer();

for(var result = 0; result < results.length; result++){
@@ -135,74 +242,108 @@ function createResult(codelet) {
row = document.createElement("tr");
//Level 2
var displayInfo = document.createElement("div"),
sidebar = document.createElement("td"),
codeElt = document.createElement("td"),
displayButton = document.createElement("td"),
hiddenInfoContainer = document.createElement("td"),
hiddenInfo = document.createElement("div");
hiddenInfo = document.createElement("div"),
cycle = document.createElement("div");
//Level 3
var title = document.createElement("span"),
site = document.createElement("span"),
dateModified = document.createElement("span"),
language = document.createElement("span"),
dateCreated = document.createElement("span"),
nextMatch = document.createElement("a"),
prevMatch = document.createElement("a"),
dateModified = document.createElement("div"),
language = document.createElement("div"),
dateCreated = document.createElement("div"),
authors = document.createElement("div");

//Classes and ID's
newDiv.classList.add('result');

displayInfo.id = 'display-info';
sidebar.id = 'sidebar';
codeElt.id = 'code';
displayButton.id = 'display-button';
hiddenInfo.id = 'hidden-info';
cycle.id = 'cycle-matches'

title.id = 'title';
site.id = 'site';
nextMatch.id = 'next-match';
nextMatch.href = '#';
prevMatch.id = 'prev-match';
prevMatch.href = '#';
dateModified.id = 'date-modified';
language.id = 'language';
dateCreated.id = 'date-created';
authors.id = 'authors';

//Add the bulk of the html
title.innerHTML = 'File <a href="' + codelet.url + '">'
title.innerHTML = ' &raquo; <a href="' + codelet.url + '">'
+ codelet.filename + '</a>';
site.innerHTML = 'on <a href="' + codelet.origin[1] + '">' + codelet.origin[0] +'</a>';
dateModified.innerHTML = 'Last modified ' + codelet.date_modified;
site.innerHTML = '<a href="' + codelet.origin[1] + '">' + codelet.origin[0] +'</a>';
nextMatch.innerHTML = 'next match';
prevMatch.innerHTML = 'prev match';
language.innerHTML = 'Language: <span>' + codelet.language + '</span>';
dateModified.innerHTML = 'Last modified: <span>' + codelet.date_modified + '</span>';
// Needs to be changed from int to string on the server
language.innerHTML = codelet.language;
dateCreated.innerHTML = 'Created ' + codelet.date_created;
authors.innerHTML = 'Authors: ';
$.each(codelet.authors, function(i, a) {
authors.innerHTML += '<a href=#>' + a + ' </a>';
dateCreated.innerHTML = 'Created: <span>' + codelet.date_created + '</span>';

var authorsHtml = 'Authors: <span>';
codelet.authors.forEach(function(a, i) {
if (i == codelet.authors.length - 1)
authorsHtml += '<a href=#>' + a + ' </a>';
else
authorsHtml += '<a href=#>' + a + ' </a>, ';
});
authors.innerHTML = authorsHtml;

sidebar.innerHTML = '';
// Needs to be processed on the server
codeElt.innerHTML = '<div id=tablecontainer>' + codelet.html_code + '</div>';

//Event binding
$(displayButton).click(function(e) {
$(hiddenInfo).toggleClass('visible');
$(this).toggleClass('active');
$(newDiv).on('mousemove', function(e) {
var holdCondition = $('.disable-hover');

if(holdCondition.length == 0) {
$(this).siblings().removeClass('display-all');
$(this).addClass('display-all');
}
});

$(newDiv).on('mouseleave', function(e) {
var holdCondition = $('.disable-hover');

if(holdCondition.length == 0)
$(this).removeClass('display-all');
});

$(nextMatch).click(function(e) {
e.stopPropagation();
e.preventDefault();
nextSymbolMatch();
});

$(prevMatch).click(function(e) {
e.stopPropagation();
e.preventDefault();
previousSymbolMatch();
});

//Finish and append elements to parent elements
hiddenInfo.appendChild(dateCreated);
hiddenInfo.appendChild(dateModified);
hiddenInfo.appendChild(authors);
hiddenInfo.appendChild(language);
hiddenInfo.appendChild(authors);

hiddenInfoContainer.appendChild(hiddenInfo);

row.appendChild(sidebar);
row.appendChild(codeElt);
row.appendChild(hiddenInfoContainer);
row.appendChild(displayButton);
table.appendChild(row);

displayInfo.appendChild(title);
displayInfo.appendChild(site);
displayInfo.appendChild(title);

cycle.appendChild(prevMatch);
cycle.appendChild(nextMatch);

newDiv.appendChild(displayInfo);
newDiv.appendChild(table);
@@ -210,6 +351,52 @@ function createResult(codelet) {
return newDiv;
}

function previousSymbolMatch() {
var currResult = $(".display-all"),
currMatch = currResult.find(".hll.current"),
matches = currResult.find(".hll"),
scrollDiv = currResult.find("#tablecontainer");

if (currMatch.length == 0)
currMatch = matches[0];
else
currMatch.removeClass('current');

var index = matches.index(currMatch.get(0)) - 1;
index = index <= 0 ? matches.length - 1 : index;
var newMatch = $(matches[index]);

scrollDiv.scrollTop(scrollDiv.scrollTop()
- scrollDiv.height() / 2
+ newMatch.position().top + newMatch.height() / 2);

newMatch.effect("highlight", {color: '#FFF'}, 750)
newMatch.addClass('current');
};

function nextSymbolMatch() {
var currResult = $(".display-all"),
currMatch = currResult.find(".hll.current"),
matches = currResult.find(".hll"),
scrollDiv = currResult.find("#tablecontainer");

if (currMatch.length == 0)
currMatch = $(matches[0]);
else
currMatch.removeClass("current");

var index = matches.index(currMatch.get(0)) + 1;
index = index >= matches.length ? 0 : index;
var newMatch = $(matches[index]);

scrollDiv.scrollTop(scrollDiv.scrollTop()
- scrollDiv.height() / 2
+ newMatch.position().top + newMatch.height() / 2);

newMatch.effect("highlight", {color: "#FFF"}, 750)
newMatch.addClass("current");
};

/*
* AJAX the current query string to the server, and return its response.
*
@@ -217,10 +404,23 @@ function createResult(codelet) {
* elements, to fill `div#results`.
*/
function queryServer(){
var resultDivs = []
var queryUrl = document.URL + "search.json?" + $.param({
"q" : searchBar.value,
"p" : searchResultsPage++
});

var resultDivs = [];
$.getJSON(queryUrl, function(result){
if("error" in result)
insertErrorMessage(result["error"]);
else
for(var codelet = 0; codelet < result["results"].length; codelet++)
resultDivs.push(result["results"][codelet]);
});

for(var result = 0; result < 20; result++){
var newDiv = createResult(testCodelet);
resultDivs.push(newDiv);
resultDivs.push(newDiv)
}

return resultDivs;
@@ -230,7 +430,7 @@ function queryServer(){
* Adds more results to `div#results`.
*/
function loadMoreResults(){
results = queryServer();
var results = queryServer();
for(var result = 0; result < results.length; result++){
var newDiv = results[result];
resultsDiv.appendChild(newDiv);
@@ -243,3 +443,16 @@ function loadMoreResults(){
result * 20);
}
}

/*
* Displays a warning message in the UI.
*
* @param msg (str) The message string.
*/
function insertErrorMessage(msg){
var error = $("<div id='error'><span>Error: </span></div>");
error.append(msg);
resultsDiv.appendChild(error[0]);
}

// loadMoreResults();

+ 0
- 7
static/js/lib/typeahead.bundle.min.js
File diff suppressed because it is too large
Näytä tiedosto


+ 5
- 0
static/sass/_mixins.sass Näytä tiedosto

@@ -10,6 +10,11 @@
-o-#{$property}: $value
#{$property}: $value

// Add portable opacity style.
@mixin opaque($opacity)
@include vendor(opacity, $opacity)
filter: alpha(opacity=$opacity)

.t1
@include vendor(transition, all 0.1s ease-out)



+ 157
- 101
static/sass/index.sass Näytä tiedosto

@@ -6,9 +6,8 @@
@import variables

$minSearchFieldsWidth: 490px
$resultWidth: 830px
$sidebarWidth: 30px
$codeWidth: 500px
$resultWidth: 1000px
$codeWidth: 650px
$hiddenInfoWidth: 250px

.ui-datepicker
@@ -23,6 +22,54 @@ $hiddenInfoWidth: 250px
>li.ui-menu-item a.ui-state-focus
@include vendor(transition, background-color 0.3s ease-out)

div#body
@extend .t3

&.faded
@include opaque(0.8)

div#hotkey-help
$width: 40%

background-color: white
border: 1px solid $baseColor3
left: 50% - $width / 2
min-width: 400px
padding: 35px
position: fixed
top: 30%
width: $width
z-index: 200

&.hidden
display: none

div
border-bottom: 1px solid $baseColor2
color: $baseColor1
font-size: 130%
padding-bottom: 8px
text-align: center

ul
list-style: none
margin-left: auto
margin-right: auto
position: relative
width: 300px

li
margin-bottom: 4px

span.hotkey
color: $baseColor1
font-family: monospace
font-size: 130%
font-weight: bold

span.seperator
color: $baseColor2

div#search-field
@extend .t2

@@ -34,6 +81,7 @@ div#search-field
max-height: 100px
right: 0
position: absolute
z-index: 2
top: 0
width: 40%

@@ -103,7 +151,6 @@ div#search-field

&.partly-visible
margin-top: 0%
padding-bottom: 3%
position: absolute
width: 100%

@@ -121,6 +168,11 @@ div#search-field
margin-right: auto
width: 60%

input:hover
@extend .t3

border: 1px solid $baseColor1

div#advanced-search
background-color: white
border: 1px solid $baseColor3
@@ -237,7 +289,7 @@ div#advanced-search

#search-groups
margin-top: 1%
max-height: 93%
max-height: 87%
overflow-y: auto
width: 75%

@@ -286,112 +338,116 @@ div#results
margin-right: auto
width: 80%

/* TODO:
1) Sidebar
- Add way to cycle through hits in the code.
2) Hidden info
- Add links for authors.
- Remove language field.
3) Header
- Add an icon for the website.
- Add language tag.
4) Code body
- Add highlighting.*/
div.result
width: $resultWidth
height: 200px
margin-top: 2%
margin-bottom: 6%

#display-info
font-size: 1.2em

a
text-decoration: none

&:hover
color: orange

#title
margin-right: 10px

#site
text-transform: capitalize
a
text-decoration: none

&:hover
color: orange

div#error
font-size: 170%
margin-top: 22%
text-align: center

span
color: $baseColor1
font-size: 150%

&.disable-hover
pointer-events: none

div.result
@extend .t3

width: $resultWidth
height: 200px
margin-bottom: 100%
pointer-events: auto

table
border-collapse: collapse
height: inherit

tr
@extend .t3
@include opaque(0.8)

table
border-collapse: collapse
border: 1px solid $baseColor3
height: inherit

tr
height: inherit

#sidebar
width: $sidebarWidth
background-color: #eee
border-right: 1px solid $baseColor3
height: inherit

#code
width: $codeWidth
height: inherit
border-right: 1px solid $baseColor3

#tablecontainer
overflow: scroll
width: 100%
height: inherit
background-color: #49483e

table
table-layout:fixed
border-collapse: collapse
border: none
font-family: monospace

#display-button
width: 25px
background: url(http://icons.iconarchive.com/icons/visualpharm/icons8-metro-style/512/Image-Edition-Tools-Arrow-icon.png)
background-size: 25px 25px
background-repeat: no-repeat
background-position: center
&.cascade
@extend .t1
margin-bottom: 15%

&:hover
background-color: #eee
&.display-all table tr
@include opaque(1.0)

&.active
@include vendor(transform, rotateY(180deg))
div#display-info
font-size: 1.3em
padding: 5px 0px 5px 5px
width: 100%

#hidden-info
width: $hiddenInfoWidth
margin-left: -$hiddenInfoWidth
height: 100%
padding-top: 50px
text-align: center
font-size: 1em
line-height: 1.5em
@include vendor(transition, margin-left 0.2s ease-in-out)
#title
margin-right: 10px

&.visible
margin-left: 0px
#site
text-transform: capitalize

#date-created
display: inline-block
td#code
@include vendor(transition, width 0.2s ease-in-out)

#date-modified
display: block
width: $codeWidth
height: inherit
padding: 0px
border: 1px solid #bbb

#language
display: inline-block
font-weight: bold
color: orange
#tablecontainer
overflow: hidden
width: 100%
height: inherit
background-color: #49483e
position: relative
z-index: 1

#authors
a
text-decoration: none
table
border-collapse: collapse
font-family: monospace

&:hover
color: orange
.linenos
padding-left: 1%

&.cascade
@extend .t3
pre
margin-top: 5px

.code pre
margin-top: 5px

.hll
background: #5B5A51

div#hidden-info
width: $hiddenInfoWidth
margin-left: -$hiddenInfoWidth - 10px
height: 100%
padding-top: 40px
font-size: 1.2em
line-height: 1.5em
position: relative
z-index: 0

@include vendor(transition, margin-left 0.2s ease-in-out)

.display-all &
margin-left: 0px
padding-left: 20px

span
font-family: monospace
color: $baseColor1
float: right

div
display: block

#authors
a
font-family: monospace

+ 14
- 3
templates/index.html Näytä tiedosto

@@ -1,14 +1,13 @@
= extends "layout.html"

= block title
Home
home
= endblock

= block head
{{ assets.tag("lib/jqueryui.custom.min.css") }}
{{ assets.tag("lib/jquery.min.js") }}
{{ assets.tag("lib/jquery-ui.min.js") }}
{{ assets.tag("lib/typeahead.bundle.min.js") }}
{{ assets.tag("lib/highlight.css") }}

{{ assets.tag("index.css") }}
@@ -30,7 +29,7 @@

<form id="search-bar">
<input type="text" name="query"
><button id="advanced-search" title="advanced search">
><button id="advanced-search" title="advanced search" type="button">
<img src="static/img/search_bar_magnifying_glass.png">
</button>

@@ -100,3 +99,15 @@
{{ assets.tag("index.js") }}
{{ assets.tag("index.advanced-search-form.js") }}
= endblock

= block after_body
<div id="hotkey-help" class="hidden">
<div>Hotkeys</div>
<ul>
<li><span class="hotkey">k</span> <span class="seperator">:</span> move window up to the previous result</li>
<li><span class="hotkey">j</span> <span class="seperator">:</span> move window down to the next result</li>
<li><span class="hotkey">h</span> <span class="seperator">:</span> move to the previous symbol match</li>
<li><span class="hotkey">l</span> <span class="seperator">:</span> move to the next symbol match</li>
</ul>
</div>
= endblock

+ 8
- 2
templates/layout.html Näytä tiedosto

@@ -4,8 +4,11 @@
<html>
<head>
<title>
= block title
= endblock
bitshift &laquo;
= filter lower
= block title
= endblock
= endfilter
</title>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
@@ -30,6 +33,9 @@
</div>
</div>

= block after_body
= endblock

<div id="footer">
<a href="/">home</a>
<a href="/about">about</a>


+ 40
- 0
test/resources/app.py Näytä tiedosto

@@ -0,0 +1,40 @@
"""
Module to contain all the project's Flask server plumbing.
"""

from flask import Flask
from flask import render_template, session

from bitshift import assets
# from bitshift.database import Database
# from bitshift.query import parse_query

app = Flask(__name__)
app.config.from_object("bitshift.config")

app_env = app.jinja_env
app_env.line_statement_prefix = "="
app_env.globals.update(assets=assets)

# database = Database()

@app.route("/")
def index():
return render_template("index.html")

@app.route("/search/<query>")
def search(query):
# tree = parse_query(query)
# database.search(tree)
pass

@app.route("/about")
def about():
return render_template("about.html")

@app.route("/developers")
def developers():
return render_template("developers.html")

if __name__ == "__main__":
app.run(debug=True)

Ladataan…
Peruuta
Tallenna