diff options
Diffstat (limited to 'theme/javascript')
-rw-r--r-- | theme/javascript/app.js | 9 | ||||
-rw-r--r-- | theme/javascript/core/exercise.js | 2 | ||||
-rw-r--r-- | theme/javascript/core/keyboard.js | 14 | ||||
-rw-r--r-- | theme/javascript/core/progress.js | 2 | ||||
-rw-r--r-- | theme/javascript/core/search.js | 106 | ||||
-rw-r--r-- | theme/javascript/core/sidebar.js | 32 | ||||
-rw-r--r-- | theme/javascript/core/state.js | 14 |
7 files changed, 154 insertions, 25 deletions
diff --git a/theme/javascript/app.js b/theme/javascript/app.js index 8fdd114..34247ca 100644 --- a/theme/javascript/app.js +++ b/theme/javascript/app.js @@ -8,10 +8,10 @@ require([ "core/keyboard", "core/exercise", "core/progress", - "core/sidebar" -], function($, storage, analytic, sharing, _state, keyboard, exercise, progress, sidebar){ + "core/sidebar", + "core/search" +], function($, storage, analytic, sharing, state, keyboard, exercise, progress, sidebar, search){ $(document).ready(function() { - var state = _state(); var $book = state.$book; // Initialize storage @@ -20,6 +20,9 @@ require([ // Init sidebar sidebar.init(); + // Load search + search.init(); + // Init keyboard keyboard.init(); diff --git a/theme/javascript/core/exercise.js b/theme/javascript/core/exercise.js index db278b8..f890f2a 100644 --- a/theme/javascript/core/exercise.js +++ b/theme/javascript/core/exercise.js @@ -38,7 +38,7 @@ define([ // Prepare all exercise var init = function() { - state().$book.find("section.exercise").each(function() { + state.$book.find("section.exercise").each(function() { prepareExercise($(this)); }); }; diff --git a/theme/javascript/core/keyboard.js b/theme/javascript/core/keyboard.js index 05e939e..5bbdcf2 100644 --- a/theme/javascript/core/keyboard.js +++ b/theme/javascript/core/keyboard.js @@ -2,8 +2,9 @@ define([ "jQuery", "Mousetrap", "core/navigation", - "core/sidebar" -], function($, Mousetrap, navigation, sidebar){ + "core/sidebar", + "core/search" +], function($, Mousetrap, navigation, sidebar, search){ // Bind keyboard shortcuts var init = function() { // Next @@ -23,9 +24,16 @@ define([ sidebar.toggle(); return false; }); + + // Toggle Search + Mousetrap.bind(['f'], function(e) { + search.toggle(); + return false; + }); }; return { - init: init + init: init, + search: search }; });
\ No newline at end of file diff --git a/theme/javascript/core/progress.js b/theme/javascript/core/progress.js index 755f111..d074cae 100644 --- a/theme/javascript/core/progress.js +++ b/theme/javascript/core/progress.js @@ -6,7 +6,7 @@ define([ ], function(_, $, storage, state) { // Get current level var getCurrentLevel = function() { - return state().level; + return state.level; }; // Return all levels diff --git a/theme/javascript/core/search.js b/theme/javascript/core/search.js new file mode 100644 index 0000000..bc1a31b --- /dev/null +++ b/theme/javascript/core/search.js @@ -0,0 +1,106 @@ +define([ + "jQuery", + "lodash", + "lunr", + "utils/storage", + "core/state", + "core/sidebar" +], function($, _, lunr, storage, state, sidebar) { + var index = null; + var $searchBar = state.$book.find(".book-search"); + var $searchInput = $searchBar.find("input"); + + // Use a specific idnex + var useIndex = function(data) { + index = lunr.Index.load(data); + }; + + // Load complete index + var loadIndex = function() { + var cacheKey = state.revision+":"+"searchIndex"; + var cache = storage.get(cacheKey); + + if (cache) return useIndex(cache); + + $.getJSON(state.basePath+"/search_index.json") + .then(function(index) { + storage.set(cacheKey, index); + return index; + }) + .then(useIndex); + }; + + // Search for a term + var search = function(q) { + if (!index) return; + var results = _.chain(index.search(q)) + .map(function(result) { + var parts = result.ref.split("#") + return { + path: parts[0], + hash: parts[1] + } + }) + .value(); + + return results; + }; + + // Toggle search bar + var toggleSearch = function(_state) { + if (state != null && isSearchOpen() == _state) return; + + state.$book.toggleClass("with-search", _state); + + // If search bar is open: focus input + if (isSearchOpen()) { + sidebar.toggle(true); + $searchInput.focus(); + } else { + $searchInput.blur(); + $searchInput.val(""); + sidebar.filter(null); + } + }; + + // Return true if search bar is open + var isSearchOpen = function() { + return state.$book.hasClass("with-search"); + }; + + + var init = function() { + loadIndex(); + + // Toggle search + state.$book.find(".book-header .toggle-search").click(function(e) { + e.preventDefault(); + toggleSearch(); + }); + + $searchInput.keyup(function(e) { + var key = (e.keyCode ? e.keyCode : e.which); + var q = $(this).val(); + + if (key == 27) { + e.preventDefault(); + toggleSearch(false); + return; + } + if (q.length == 0) { + sidebar.filter(null); + } else { + var results = search(q); + sidebar.filter( + _.pluck(results, "path") + ); + } + }); + }; + + return { + init: init, + search: search, + toggle: toggleSearch + }; +});
\ No newline at end of file diff --git a/theme/javascript/core/sidebar.js b/theme/javascript/core/sidebar.js index c36f4fe..d318676 100644 --- a/theme/javascript/core/sidebar.js +++ b/theme/javascript/core/sidebar.js @@ -1,32 +1,31 @@ define([ + "lodash", "utils/storage", "utils/platform", "core/state" -], function(storage, platform, state) { +], function(_, storage, platform, state) { + var $summary = state.$book.find(".book-summary"); // Toggle sidebar with or withour animation var toggleSidebar = function(_state, animation) { - if (-state != null && isOpen() == _state) return; + if (state != null && isOpen() == _state) return; if (animation == null) animation = true; - var $book = state().$book; - $book.toggleClass("without-animation", !animation); - $book.toggleClass("with-summary", _state); + state.$book.toggleClass("without-animation", !animation); + state.$book.toggleClass("with-summary", _state); storage.set("sidebar", isOpen()); }; // Return true if sidebar is open var isOpen = function() { - return state().$book.hasClass("with-summary"); + return state.$book.hasClass("with-summary"); }; // Prepare sidebar: state and toggle button var init = function() { - var $book = state().$book; - // Toggle summary - $book.find(".book-header .toggle-summary").click(function(e) { + state.$book.find(".book-header .toggle-summary").click(function(e) { e.preventDefault(); toggleSidebar(); }); @@ -37,8 +36,21 @@ define([ } }; + // Filter summary with a list of path + var filterSummary = function(paths) { + $summary.find("li").each(function() { + var path = $(this).data("path"); + var st = paths == null || _.contains(paths, path); + + $(this).toggle(st); + if (st) $(this).parents("li").show(); + }); + }; + return { + $el: $summary, init: init, - toggle: toggleSidebar + toggle: toggleSidebar, + filter: filterSummary } });
\ No newline at end of file diff --git a/theme/javascript/core/state.js b/theme/javascript/core/state.js index fc67d7b..79876b9 100644 --- a/theme/javascript/core/state.js +++ b/theme/javascript/core/state.js @@ -1,14 +1,14 @@ define([ "jQuery" ], function() { - return function() { - var $book = $(".book"); + var $book = $(".book"); - return { - '$book': $book, + return { + '$book': $book, - 'githubId': $book.data("github"), - 'level': $book.data("level") - }; + 'githubId': $book.data("github"), + 'level': $book.data("level"), + 'basePath': $book.data("basepath"), + 'revision': $book.data("revision") }; });
\ No newline at end of file |