mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-18 16:45:11 +00:00
Add back theme
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
define([
|
||||
"jQuery"
|
||||
], function($) {
|
||||
var events = $({});
|
||||
|
||||
return events;
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/storage"
|
||||
], function($, storage) {
|
||||
var fontState;
|
||||
|
||||
var THEMES = {
|
||||
"white": 0,
|
||||
"sepia": 1,
|
||||
"night": 2
|
||||
};
|
||||
|
||||
var FAMILY = {
|
||||
"serif": 0,
|
||||
"sans": 1
|
||||
};
|
||||
|
||||
var enlargeFontSize = function(e){
|
||||
if (fontState.size < 4){
|
||||
fontState.size++;
|
||||
fontState.save();
|
||||
}
|
||||
};
|
||||
|
||||
var reduceFontSize = function(e){
|
||||
if (fontState.size > 0){
|
||||
fontState.size--;
|
||||
fontState.save();
|
||||
}
|
||||
};
|
||||
|
||||
var changeFontFamily = function(){
|
||||
var index = $(this).data("font");
|
||||
|
||||
fontState.family = index;
|
||||
fontState.save();
|
||||
};
|
||||
|
||||
var changeColorTheme = function(){
|
||||
var $book = $(".book");
|
||||
var index = $(this).data("theme");
|
||||
|
||||
if (fontState.theme !== 0)
|
||||
$book.removeClass("color-theme-"+fontState.theme);
|
||||
|
||||
fontState.theme = index;
|
||||
if (fontState.theme !== 0)
|
||||
$book.addClass("color-theme-"+fontState.theme);
|
||||
|
||||
fontState.save();
|
||||
};
|
||||
|
||||
var update = function() {
|
||||
var $book = $(".book");
|
||||
|
||||
$(".font-settings .font-family-list li").removeClass("active");
|
||||
$(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active");
|
||||
|
||||
$book[0].className = $book[0].className.replace(/\bfont-\S+/g, '');
|
||||
$book.addClass("font-size-"+fontState.size);
|
||||
$book.addClass("font-family-"+fontState.family);
|
||||
|
||||
if(fontState.theme !== 0) {
|
||||
$book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, '');
|
||||
$book.addClass("color-theme-"+fontState.theme);
|
||||
}
|
||||
};
|
||||
|
||||
var init = function(config) {
|
||||
var $toggle, $bookBody, $dropdown, $book;
|
||||
|
||||
//Find DOM elements.
|
||||
$book = $(".book");
|
||||
$toggle = $(".book-header .toggle-font-settings");
|
||||
$dropdown = $("#font-settings-wrapper .dropdown-menu");
|
||||
$bookBody = $(".book-body");
|
||||
|
||||
// Instantiate font state object
|
||||
fontState = storage.get("fontState", {
|
||||
size: config.size || 2,
|
||||
family: FAMILY[config.family || "sans"],
|
||||
theme: THEMES[config.theme || "white"]
|
||||
});
|
||||
fontState.save = function(){
|
||||
storage.set("fontState",fontState);
|
||||
update();
|
||||
};
|
||||
|
||||
update();
|
||||
|
||||
//Add event listeners
|
||||
$(document).on('click', "#enlarge-font-size", enlargeFontSize);
|
||||
$(document).on('click', "#reduce-font-size", reduceFontSize);
|
||||
|
||||
$(document).on('click', "#font-settings-wrapper .font-family-list .button", changeFontFamily);
|
||||
$(document).on('click', "#font-settings-wrapper .color-theme-list .button", changeColorTheme);
|
||||
};
|
||||
|
||||
return {
|
||||
init: init,
|
||||
update: update
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"lodash",
|
||||
"core/state"
|
||||
], function($, _, state) {
|
||||
var index = null;
|
||||
|
||||
// Use a specific idnex
|
||||
var useIndex = function(data) {
|
||||
index = data;
|
||||
};
|
||||
|
||||
// Load complete index
|
||||
var loadIndex = function() {
|
||||
return $.getJSON(state.basePath+"/glossary_index.json")
|
||||
.then(useIndex);
|
||||
};
|
||||
|
||||
// Get index and return a promise
|
||||
var getIndex = function() {
|
||||
var d = $.Deferred();
|
||||
|
||||
if (index) {
|
||||
d.resolve(index);
|
||||
} else {
|
||||
loadIndex().done(function(){
|
||||
d.resolve(index);
|
||||
}).fail(d.reject);
|
||||
}
|
||||
|
||||
return d.promise();
|
||||
}
|
||||
|
||||
$.fn.replaceText = function( search, replace, text_only ) {
|
||||
return this.each(function(){
|
||||
var node = this.firstChild,
|
||||
val,
|
||||
new_val,
|
||||
|
||||
// Elements to be removed at the end.
|
||||
remove = [];
|
||||
|
||||
// Only continue if firstChild exists.
|
||||
if ( node ) {
|
||||
|
||||
// Loop over all childNodes.
|
||||
do {
|
||||
|
||||
// Only process text nodes.
|
||||
if ( node.nodeType === 3 ) {
|
||||
|
||||
// The original node value.
|
||||
val = node.nodeValue;
|
||||
|
||||
// The new value.
|
||||
new_val = val.replace( search, replace );
|
||||
|
||||
// Only replace text if the new value is actually different!
|
||||
if ( new_val !== val ) {
|
||||
|
||||
if ( !text_only && /</.test( new_val ) ) {
|
||||
// The new value contains HTML, set it in a slower but far more
|
||||
// robust way.
|
||||
$(node).before( new_val );
|
||||
|
||||
// Don't remove the node yet, or the loop will lose its place.
|
||||
remove.push( node );
|
||||
} else {
|
||||
// The new value contains no HTML, so it can be set in this
|
||||
// very fast, simple way.
|
||||
node.nodeValue = new_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while ( node = node.nextSibling );
|
||||
}
|
||||
|
||||
// Time to remove those elements!
|
||||
remove.length && $(remove).remove();
|
||||
});
|
||||
};
|
||||
|
||||
var pregQuote = function( str ) {
|
||||
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
// Bind click on glossary item
|
||||
$(document).on("click", ".book-body .page-wrapper .page-inner .glossary-term", function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
location.href = state.basePath+"/GLOSSARY.html#"+$(e.currentTarget).data("glossary-term");
|
||||
});
|
||||
};
|
||||
|
||||
var replaceTerm = function($el, term) {
|
||||
var r = new RegExp( "\\b(" + pregQuote(term.name.toLowerCase()) + ")\\b" , 'gi' );
|
||||
|
||||
$el.find("*").replaceText(r, function(match) {
|
||||
return "<span class='glossary-term' data-glossary-term='"+term.id+"' title='"+term.description+"'>"+match+"</span>";
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var prepare = function() {
|
||||
getIndex()
|
||||
.done(function() {
|
||||
_.each(index, _.partial(replaceTerm, $(".book-body .page-wrapper .page-inner")));
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: init,
|
||||
prepare: prepare
|
||||
};
|
||||
});
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"Mousetrap",
|
||||
"core/navigation",
|
||||
"core/sidebar",
|
||||
"core/search"
|
||||
], function($, Mousetrap, navigation, sidebar, search){
|
||||
// Bind keyboard shortcuts
|
||||
var init = function() {
|
||||
// Next
|
||||
Mousetrap.bind(['right'], function(e) {
|
||||
navigation.goNext();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Prev
|
||||
Mousetrap.bind(['left'], function(e) {
|
||||
navigation.goPrev();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Toggle Summary
|
||||
Mousetrap.bind(['s'], function(e) {
|
||||
sidebar.toggle();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Toggle Search
|
||||
Mousetrap.bind(['f'], function(e) {
|
||||
search.toggle();
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
define([
|
||||
"jQuery"
|
||||
], function($) {
|
||||
var showLoading = function(p) {
|
||||
$(".book").addClass("is-loading");
|
||||
p.always(function() {
|
||||
$(".book").removeClass("is-loading");
|
||||
});
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
return {
|
||||
show: showLoading
|
||||
};
|
||||
});
|
||||
Executable
+151
@@ -0,0 +1,151 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/url",
|
||||
"core/events",
|
||||
"core/state",
|
||||
"core/progress",
|
||||
"core/loading",
|
||||
"core/search",
|
||||
"core/glossary"
|
||||
], function($, URL, events, state, progress, loading, search, glossary) {
|
||||
var prev, next;
|
||||
|
||||
var usePushState = (typeof history.pushState !== "undefined");
|
||||
|
||||
var handleNavigation = function(relativeUrl, push) {
|
||||
var url = URL.join(window.location.pathname, relativeUrl);
|
||||
console.log("navigate to ", url, "baseurl="+relativeUrl, "current="+window.location.pathname);
|
||||
|
||||
if (!usePushState) {
|
||||
// Refresh the page to the new URL if pushState not supported
|
||||
location.href = relativeUrl;
|
||||
return
|
||||
}
|
||||
|
||||
return loading.show($.get(url)
|
||||
.done(function (html) {
|
||||
// Push url to history
|
||||
if (push) history.pushState({ path: url }, null, url);
|
||||
|
||||
// Replace html content
|
||||
html = html.replace( /<(\/?)(html|head|body)([^>]*)>/ig, function(a,b,c,d){
|
||||
return '<' + b + 'div' + ( b ? '' : ' data-element="' + c + '"' ) + d + '>';
|
||||
});
|
||||
|
||||
var $page = $(html);
|
||||
var $pageHead = $page.find("[data-element=head]");
|
||||
var $pageBody = $page.find('.book');
|
||||
|
||||
// Merge heads
|
||||
var headContent = $pageHead.html()
|
||||
|
||||
$("head style").each(function() {
|
||||
headContent = headContent + this.outerHTML
|
||||
});
|
||||
$("head").html(headContent);
|
||||
|
||||
// Merge body
|
||||
var bodyClass = $(".book").attr("class");
|
||||
var scrollPosition = $('.book-summary .summary').scrollTop();
|
||||
$pageBody.toggleClass("with-summary", $(".book").hasClass("with-summary"))
|
||||
|
||||
$(".book").replaceWith($pageBody);
|
||||
$(".book").attr("class", bodyClass);
|
||||
$('.book-summary .summary').scrollTop(scrollPosition);
|
||||
|
||||
// Update state
|
||||
state.update($("html"));
|
||||
// recover search keyword
|
||||
search.recover();
|
||||
preparePage();
|
||||
})
|
||||
.fail(function (e) {
|
||||
location.href = relativeUrl;
|
||||
}));
|
||||
};
|
||||
|
||||
var updateNavigationPosition = function() {
|
||||
var bodyInnerWidth, pageWrapperWidth;
|
||||
|
||||
bodyInnerWidth = parseInt($('.body-inner').css('width'), 10);
|
||||
pageWrapperWidth = parseInt($('.page-wrapper').css('width'), 10);
|
||||
$('.navigation-next').css('margin-right', (bodyInnerWidth - pageWrapperWidth) + 'px');
|
||||
};
|
||||
|
||||
var preparePage = function() {
|
||||
var $pageWrapper = $(".book-body .page-wrapper");
|
||||
|
||||
// Show progress
|
||||
progress.show();
|
||||
|
||||
// Update navigation position
|
||||
updateNavigationPosition();
|
||||
|
||||
// Set glossary items
|
||||
glossary.prepare();
|
||||
|
||||
// Reset scroll
|
||||
$pageWrapper.scrollTop(0);
|
||||
|
||||
// Focus on content
|
||||
$pageWrapper.focus();
|
||||
|
||||
// Notify
|
||||
events.trigger("page.change");
|
||||
};
|
||||
|
||||
var handlePagination = function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
var url = $(this).attr('href');
|
||||
if (url) handleNavigation(url, true);
|
||||
};
|
||||
|
||||
var goNext = function() {
|
||||
var url = $(".navigation-next").attr("href");
|
||||
if (url) handleNavigation(url, true);
|
||||
};
|
||||
|
||||
var goPrev = function() {
|
||||
var url = $(".navigation-prev").attr("href");
|
||||
if (url) handleNavigation(url, true);
|
||||
};
|
||||
|
||||
|
||||
|
||||
var init = function() {
|
||||
// Prevent cache so that using the back button works
|
||||
// See: http://stackoverflow.com/a/15805399/983070
|
||||
$.ajaxSetup({
|
||||
cache: false
|
||||
});
|
||||
|
||||
// Recreate first page when the page loads.
|
||||
history.replaceState({ path: window.location.href }, '');
|
||||
|
||||
// Back Button Hijacking :(
|
||||
window.onpopstate = function (event) {
|
||||
if (event.state === null) {
|
||||
return;
|
||||
}
|
||||
return handleNavigation(event.state.path, false);
|
||||
};
|
||||
|
||||
$(document).on('click', ".navigation-prev", handlePagination);
|
||||
$(document).on('click', ".navigation-next", handlePagination);
|
||||
$(document).on('click', ".summary [data-path] a", handlePagination);
|
||||
|
||||
$(window).resize(updateNavigationPosition);
|
||||
|
||||
// Prepare current page
|
||||
preparePage();
|
||||
};
|
||||
|
||||
return {
|
||||
init: init,
|
||||
goNext: goNext,
|
||||
goPrev: goPrev
|
||||
};
|
||||
});
|
||||
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
define([
|
||||
"lodash",
|
||||
"jQuery",
|
||||
"utils/storage",
|
||||
"core/state"
|
||||
], function(_, $, storage, state) {
|
||||
// Get current level
|
||||
var getCurrentLevel = function() {
|
||||
return state.level;
|
||||
};
|
||||
|
||||
// Return all levels
|
||||
var getLevels = function () {
|
||||
var levels = $(".book-summary li[data-level]");
|
||||
|
||||
return _.map(levels, function(level) {
|
||||
return $(level).data("level").toString();
|
||||
});
|
||||
};
|
||||
|
||||
// Return a map chapter -> number (timestamp)
|
||||
var getProgress = function () {
|
||||
// Current level
|
||||
var progress = storage.get("progress", {});
|
||||
|
||||
// Levels
|
||||
var levels = getLevels();
|
||||
|
||||
_.each(levels, function(level) {
|
||||
progress[level] = progress[level] || 0;
|
||||
});
|
||||
|
||||
return progress;
|
||||
};
|
||||
|
||||
// Change value of progress for a level
|
||||
var markProgress = function (level, state) {
|
||||
var progress = getProgress();
|
||||
|
||||
if (state == null) {
|
||||
state = true;
|
||||
}
|
||||
|
||||
progress[level] = state
|
||||
? Date.now()
|
||||
: 0;
|
||||
|
||||
storage.set("progress", progress);
|
||||
};
|
||||
|
||||
// Show progress
|
||||
var showProgress = function () {
|
||||
var progress = getProgress();
|
||||
var $summary = $(".book-summary");
|
||||
|
||||
_.each(progress, function (value, level) {
|
||||
$summary.find("li[data-level='"+level+"']").toggleClass("done", value > 0);
|
||||
});
|
||||
|
||||
// Mark current progress if we have not already
|
||||
if (!progress[getCurrentLevel()]) {
|
||||
markProgress(getCurrentLevel(), true);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
'current': getCurrentLevel,
|
||||
'levels': getLevels,
|
||||
'get': getProgress,
|
||||
'mark': markProgress,
|
||||
'show': showProgress
|
||||
};
|
||||
});
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"lodash",
|
||||
"lunr",
|
||||
"utils/storage",
|
||||
"core/state",
|
||||
"core/sidebar"
|
||||
], function($, _, lunr, storage, state, sidebar) {
|
||||
var index = null;
|
||||
|
||||
// Use a specific idnex
|
||||
var useIndex = function(data) {
|
||||
index = lunr.Index.load(data);
|
||||
};
|
||||
|
||||
// Load complete index
|
||||
var loadIndex = function() {
|
||||
$.getJSON(state.basePath+"/search_index.json")
|
||||
.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;
|
||||
|
||||
var $searchInput = $(".book-search input");
|
||||
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
|
||||
$(document).on("click", ".book-header .toggle-search", function(e) {
|
||||
e.preventDefault();
|
||||
toggleSearch();
|
||||
});
|
||||
|
||||
|
||||
// Type in search bar
|
||||
$(document).on("keyup", ".book-search input", 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);
|
||||
storage.remove("keyword");
|
||||
} else {
|
||||
var results = search(q);
|
||||
sidebar.filter(
|
||||
_.pluck(results, "path")
|
||||
);
|
||||
storage.set("keyword", q);
|
||||
}
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
// filter sidebar menu with current search keyword
|
||||
var recoverSearch = function() {
|
||||
var keyword = storage.get("keyword", "");
|
||||
if(keyword.length > 0) {
|
||||
if(!isSearchOpen()){
|
||||
toggleSearch();
|
||||
}
|
||||
sidebar.filter(_.pluck(search(keyword), "path"));
|
||||
}
|
||||
$(".book-search input").val(keyword);
|
||||
};
|
||||
|
||||
return {
|
||||
init: init,
|
||||
search: search,
|
||||
toggle: toggleSearch,
|
||||
recover:recoverSearch
|
||||
};
|
||||
});
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"lodash",
|
||||
"utils/storage",
|
||||
"utils/platform",
|
||||
"core/state"
|
||||
], function($, _, storage, platform, state) {
|
||||
// Toggle sidebar with or withour animation
|
||||
var toggleSidebar = function(_state, animation) {
|
||||
if (state != null && isOpen() == _state) return;
|
||||
if (animation == null) animation = true;
|
||||
|
||||
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");
|
||||
};
|
||||
|
||||
// Prepare sidebar: state and toggle button
|
||||
var init = function() {
|
||||
// Toggle summary
|
||||
$(document).on("click", ".book-header .toggle-summary", function(e) {
|
||||
e.preventDefault();
|
||||
toggleSidebar();
|
||||
});
|
||||
|
||||
// Init last state if not mobile
|
||||
if (!platform.isMobile) {
|
||||
toggleSidebar(storage.get("sidebar", true), false);
|
||||
}
|
||||
};
|
||||
|
||||
// Filter summary with a list of path
|
||||
var filterSummary = function(paths) {
|
||||
var $summary = $(".book-summary");
|
||||
|
||||
$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 {
|
||||
init: init,
|
||||
toggle: toggleSidebar,
|
||||
filter: filterSummary
|
||||
}
|
||||
});
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
define([
|
||||
"jQuery"
|
||||
], function() {
|
||||
var state = {};
|
||||
|
||||
state.update = function(dom) {
|
||||
var $book = $(dom.find(".book"));
|
||||
|
||||
state.$book = $book;
|
||||
state.level = $book.data("level");
|
||||
state.basePath = $book.data("basepath");
|
||||
state.revision = $book.data("revision");
|
||||
};
|
||||
|
||||
state.update($);
|
||||
|
||||
return state;
|
||||
});
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
define([
|
||||
"jQuery",
|
||||
"utils/storage",
|
||||
"utils/sharing",
|
||||
"utils/dropdown",
|
||||
|
||||
"core/events",
|
||||
"core/font-settings",
|
||||
"core/state",
|
||||
"core/keyboard",
|
||||
"core/navigation",
|
||||
"core/progress",
|
||||
"core/sidebar",
|
||||
"core/search",
|
||||
"core/glossary"
|
||||
], function($, storage, sharing, dropdown, events, fontSettings, state, keyboard, navigation, progress, sidebar, search, glossary){
|
||||
var start = function(config) {
|
||||
var $book;
|
||||
$book = state.$book;
|
||||
|
||||
// Init sidebar
|
||||
sidebar.init();
|
||||
|
||||
// Load search
|
||||
search.init();
|
||||
|
||||
// Load glossary
|
||||
glossary.init();
|
||||
|
||||
// Init keyboard
|
||||
keyboard.init();
|
||||
|
||||
// Bind sharing button
|
||||
sharing.init();
|
||||
|
||||
// Bind dropdown
|
||||
dropdown.init();
|
||||
|
||||
// Init navigation
|
||||
navigation.init();
|
||||
|
||||
//Init font settings
|
||||
fontSettings.init(config.fontSettings || {});
|
||||
|
||||
events.trigger("start", config);
|
||||
}
|
||||
|
||||
return {
|
||||
start: start,
|
||||
events: events,
|
||||
state: state
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
define([
|
||||
"jQuery"
|
||||
], function($) {
|
||||
|
||||
var toggleDropdown = function(e) {
|
||||
var $dropdown = $(e.currentTarget).parent().find(".dropdown-menu");
|
||||
|
||||
$dropdown.toggleClass("open");
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
var closeDropdown = function(e) {
|
||||
$(".dropdown-menu").removeClass("open");
|
||||
};
|
||||
|
||||
// Bind all dropdown
|
||||
var init = function() {
|
||||
$(document).on('click', ".toggle-dropdown", toggleDropdown);
|
||||
$(document).on('click', ".dropdown-menu", function(e){ e.stopPropagation(); });
|
||||
$(document).on("click", closeDropdown);
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
});
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
define([], function() {
|
||||
return {
|
||||
isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
||||
};
|
||||
});
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
define([
|
||||
"jQuery"
|
||||
], function($) {
|
||||
var types = {
|
||||
"twitter": function($el) {
|
||||
window.open("http://twitter.com/home?status="+encodeURIComponent($("title").text()+" "+location.href))
|
||||
},
|
||||
"facebook": function($el) {
|
||||
window.open("http://www.facebook.com/sharer/sharer.php?s=100&p[url]="+encodeURIComponent(location.href))
|
||||
},
|
||||
"google-plus": function($el) {
|
||||
window.open("https://plus.google.com/share?url="+encodeURIComponent(location.href))
|
||||
},
|
||||
"weibo": function($el) {
|
||||
window.open("http://service.weibo.com/share/share.php?content=utf-8&url="+encodeURIComponent(location.href)+"&title="+encodeURIComponent($("title").text()))
|
||||
},
|
||||
"instapaper": function($el) {
|
||||
window.open("http://www.instapaper.com/text?u="+encodeURIComponent(location.href));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Bind all sharing button
|
||||
var init = function() {
|
||||
$(document).on("click", "a[data-sharing],button[data-sharing]", function(e) {
|
||||
if (e) e.preventDefault();
|
||||
var type = $(this).data("sharing");
|
||||
|
||||
types[type]($(this));
|
||||
})
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
});
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
define(function(){
|
||||
var baseKey = "";
|
||||
|
||||
/*
|
||||
* Simple module for storing data in the browser's local storage
|
||||
*/
|
||||
return {
|
||||
setBaseKey: function(key) {
|
||||
baseKey = key;
|
||||
},
|
||||
set: function(key, value) {
|
||||
key = baseKey+":"+key;
|
||||
localStorage[key] = JSON.stringify(value);
|
||||
},
|
||||
get: function(key, def) {
|
||||
key = baseKey+":"+key;
|
||||
if (localStorage[key] === undefined) return def;
|
||||
try {
|
||||
var v = JSON.parse(localStorage[key]);
|
||||
return v == null ? def : v;;
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
return localStorage[key] || def;
|
||||
}
|
||||
},
|
||||
remove: function(key) {
|
||||
key = baseKey+":"+key;
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
define([
|
||||
"URIjs/URI"
|
||||
], function(URI) {
|
||||
// Joins path segments. Preserves initial "/" and resolves ".." and "."
|
||||
// Does not support using ".." to go above/outside the root.
|
||||
// This means that join("foo", "../../bar") will not resolve to "../bar"
|
||||
function join(baseUrl, url) {
|
||||
var theUrl = new URI(url);
|
||||
if (theUrl.is("relative")) {
|
||||
theUrl = theUrl.absoluteTo(baseUrl);
|
||||
}
|
||||
return theUrl.toString();
|
||||
}
|
||||
|
||||
// A simple function to get the dirname of a path
|
||||
// Trailing slashes are ignored. Leading slash is preserved.
|
||||
function dirname(path) {
|
||||
return join(path, "..");
|
||||
}
|
||||
|
||||
// test if a path or url is absolute
|
||||
function isAbsolute(path) {
|
||||
if (!path) return false;
|
||||
|
||||
return (path[0] == "/" || path.indexOf("http://") == 0 || path.indexOf("https://") == 0);
|
||||
}
|
||||
|
||||
return {
|
||||
dirname: dirname,
|
||||
join: join,
|
||||
isAbsolute: isAbsolute
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user