Skip to content

Commit

Permalink
Merge pull request cpprefjp#48 from cpprefjp/feature/current-page-spe…
Browse files Browse the repository at this point in the history
…cialization

現在ページに特化したUX改善集
  • Loading branch information
saki7 authored Nov 11, 2017
2 parents 2a8967b + 38b4912 commit addd1e7
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 68 deletions.
29 changes: 19 additions & 10 deletions js/kunai.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Kunai {
}))
)


try {
this.log.disableBacktrace(true)
this.log.info(`version ${KUNAI_PACKAGE.version} (https://github.com/cpprefjp/kunai/tree/v${KUNAI_PACKAGE.version})`)
Expand All @@ -38,16 +39,13 @@ class Kunai {
this.log.disableBacktrace(false)
}

if (this.opts.compat) {
this.compat = new Compat(this.log)
}

this.ui = {
navbar: null,
sidebar: null,
content: null,
}
this.initUI()
this.getSidebar = this.initSidebar()

this.wand = new Wand(this.log)

Expand All @@ -56,15 +54,21 @@ class Kunai {

async cpprefjp() {
this.load_impl(['cpprefjp', 'site'])
this.crs = await this.initCRSearch(true)
this.afterCR = this.initCRSearch(true)
this.crs = await this.afterCR
}

async boostjp() {
this.load_impl(['boostjp', 'site'])
this.crs = await this.initCRSearch(false)
this.afterCR = this.initCRSearch(false)
this.crs = await this.afterCR
}

load_impl(config) {
async load_impl(config) {
if (this.opts.compat) {
this.compat = new Compat(this.log, config)
}

const desc = config.join('/')
this.log.info(`loading (${desc})`)
$('body').addClass('kunai')
Expand Down Expand Up @@ -114,13 +118,18 @@ class Kunai {
this.ui.content = new UI.Content(l)
}

async initCRSearch(isEnabled, onDatabase) {
async onDatabase(db) {
await this.ui.sidebar.onDatabase(db)
await this.ui.sidebar.treeview.onPageID(this.meta.page_id)
}

async initCRSearch(isEnabled) {
if (!isEnabled) return null

await this.initSidebar()
await this.getSidebar

let crs = new CRSearch({
onDatabase: ::this.ui.sidebar.onDatabase,
onDatabase: ::this.onDatabase,
})
crs.database('https://cpprefjp.github.io/static/crsearch/crsearch.json')

Expand Down
5 changes: 4 additions & 1 deletion js/kunai/compat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Compat {
constructor(log) {
constructor(log, repo) {
this.log = log.makeContext('Compat')
this.repo = [].concat(repo)

this.log.info('applying...')

Expand All @@ -27,6 +28,8 @@ class Compat {
}
}

// $('#navbar-collapse ul.nav > li:nth-child(2) > a').text(repo.join('/'))

this.log.info('applied.')
} // constructor

Expand Down
8 changes: 8 additions & 0 deletions js/kunai/meta/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as Code from '../code'

import {Logger} from 'nagato'

import URL from 'url-parse'


let Marked = require('marked')
const MarkedOpts = {
Expand Down Expand Up @@ -56,6 +58,12 @@ class Meta {
this.log.info(`original_url: ${this.original_url}`, this.original_url)
this.filename = [...this.original_url.pathname.split('/')].pop()

{
let ids = this.original_url.pathname.split('/').slice(5)
ids[ids.length - 1] = ids[ids.length - 1].replace(/\.md$/, '')
this.page_id = ids
}

this.raw_url = new URL(this.original_url)
this.raw_url.host = 'raw.githubusercontent.com'
this.raw_url.pathname = this.raw_url.pathname.replace(
Expand Down
27 changes: 7 additions & 20 deletions js/kunai/ui/sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,38 +33,24 @@ class Sidebar {
this.e.addClass('legacy')
}

this.initComponents()
this.getTreeview = this.initTreeview()
}

async onDatabase(db) {
try {
this.log.info(`onDatabase`, db)

this.tree = db.getTree(this.kc)

// workaround name
for (let t of this.tree) {
if (t.root) {
const name = t.root.id.join()
const real_name = t.category.name
if (name !== real_name) {
this.log.warn(`got incorrect title '${name}'; expected = '${real_name}'. ignoring...`)
}
}
}
this.db = db

this.treeView.onData(this.tree)
let t = await this.getTreeview
await t.onData(db)

} finally {
this.e.removeClass('loading')
}
}

async initComponents() {
await this.initDynamicComponents()
}

async initDynamicComponents() {
async initTreeview() {
let e = null

if (this.legacy) {
Expand All @@ -73,14 +59,15 @@ class Sidebar {
e = $('<div>').addClass('kunai-tree').addClass('v2').appendTo(this.e)
}

this.treeView = new Treeview(
this.treeview = new Treeview(
this.log,
this.kc,
this.e,
{
legacy: this.legacy
}
)
return this.treeview
}
}

Expand Down
146 changes: 110 additions & 36 deletions js/kunai/ui/treeview.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class DOM {

this.lastBranchID = 0
this.branchPrevs = new Map

this.expandElems = new WeakMap
}

static scrollEps = 8
Expand Down Expand Up @@ -82,22 +84,23 @@ class DOM {
}
}

async createContent(e, elem, obj) {
// this.log.debug(`createContent '${obj.self.id}'`, e, elem, obj)
async createContent(obj) {
this.log.debug(`createContent '${obj.self.id}'`, obj)

switch (obj.self.id.type) {
case IType.header:
return await this.createHeaderContent(e, elem, obj)
return await this.createHeaderContent(obj)

default:
this.log.error('createContent', e, elem, obj)
this.log.error('createContent', obj)
throw new Error(`unhandled index type in createContent`)
}
}

async createHeaderContent(e, elem, h) {
async createHeaderContent(h) {
// this.log.debug(`createHeaderContent (${h.self.id.join()})`, e, elem, h)
let empty = true
let elem = this.expandElems.get(h.self.id)

if (h.classes && h.classes.length) {
empty = false
Expand Down Expand Up @@ -126,10 +129,23 @@ class DOM {
return true // this.lazyLoaders.get(h.self.id)
}

async doExpand(id, e) {
// this.log.debug(`doExpand '${id.join()}'`, id, e)
await this.lazyLoaders.get(id)(e)
$(e.target).closest('li').toggleClass('expanded')
async doExpand(id) {
// this.log.debug(`doExpand '${id.join()}'`, id)
await this.lazyLoaders.get(id)()
this.expandElems.get(id).toggleClass('expanded')
}

async scrollAt(id) {
this.log.debug(`scrollAt '${id.join()}'`, id)

const e = this.expandElems.get(id)

let broot = e.closest('.kunai-branch')
// this.log.debug(`branch root`, broot)

broot.animate({
scrollTop: e.offset().top
}, 1)
}

async kunaiBranch(me, branchFor, scrollHandler) {
Expand Down Expand Up @@ -226,18 +242,18 @@ class DOM {
}

async makeExpandable(elem, obj) {
// this.log.debug(`makeExpandable '${obj.self.id.join()}'`, elem, obj)
this.expandElems.set(obj.self.id, elem)
this.lazyLoaders.set(
obj.self.id,
async (e) => {
return await ::this.createContent(e, elem, obj)
}
async () => { await this.createContent(obj) }
)

let bar = $('<div>', {class: 'expandbar'}).appendTo(elem)

bar.append(
$('<div>', {class: 'expander'}).on('click', async (e) => {
await this.doExpand(obj.self.id, e)
$('<div>', {class: 'expander'}).on('click', async () => {
await this.doExpand(obj.self.id)
})
)

Expand Down Expand Up @@ -289,37 +305,95 @@ class Treeview {
}
}

async onData(tree) {
const runID = JSON.stringify({name: 'onData', timestamp: Date.now()})
console.time(runID)
try {
this.dom = new DOM(this.log, this.kc)
await this.onDataImpl(tree)
} finally {
console.timeEnd(runID)
async onPageID(ids) {
this.page_id = [].concat(ids)

this.page_idx_id = null
const ns_id = ids.shift()

for (const type of Object.values(IType)) {
const rvid = IndexID.composeReverseID(type, ids)
if (this.db.reverseID.has(rvid)) {
this.page_idx_id = this.db.reverseID.get(rvid)
}
}
}

async onDataImpl(tree) {
this.log.debug('data', tree)
let root = $('<ul>', {class: 'root'}).appendTo(this.root)
this.page_idx = null

const cats = this.kc.categories()
try {
if (!this.page_idx_id) {
throw new Error(`IndexID for path '${ids.join('/')}' not present in database`)
}
if (!IndexID.isClassy(this.page_idx_id.type)) {
this.log.info(`current page '${this.page_idx_id.join()}' is not classy. nothing to expand`)

} else {
this.log.info(`classy page '${this.page_idx_id.join()}'`)

for (const top of tree) {
if (top.category.index === cats.get('index').index) {
continue
for (const ns of this.db.namespaces) {
if (ns.namespace[0] !== 'reference') continue

this.log.debug(`checking Namespace '${ns.pretty_name()}'`, ns)
if (ns.indexes.has(this.page_idx_id)) {
this.page_idx = ns.indexes.get(this.page_idx_id)
}
}

if (!this.page_idx) {
throw new Error(`Index for '${this.page_idx_id.join()}' not found in any of the 'reference' namespace`)
}

const h = this.page_idx.in_header
this.log.info(`expanding current page header '${h.id.join()}'`, h, this.page_idx)

// await this.dom.doExpand(h.id)
await this.dom.doExpand(h.id)
await this.dom.scrollAt(h.id)
}

let e = $('<li>', {class: 'top', 'data-top-id': top.namespace.namespace[0]}).appendTo(root)
e.append(await this.dom.makeTitle(top))
} catch (e) {
this.log.error(`Failed to determine current page for id '${ids.join('/')}'. Sidebar will NOT work properly! (${e})`, ids)
}
}

if (top.category.index === cats.get('lang').index) {
this.processLangTop(top, e)
} else {
this.processTop(top, e)
async onData(db) {
this.db = db
this.tree = db.getTree(this.kc)

// workaround name
for (let t of this.tree) {
if (t.root) {
const name = t.root.id.join()
const real_name = t.category.name
if (name !== real_name) {
this.log.warn(`got incorrect title '${name}'; expected = '${real_name}'. ignoring...`)
}
}
}

this.dom = new DOM(this.log, this.kc)
await this.onDataImpl()
}

async onDataImpl() {
this.log.debug('data', this.tree)
let root = $('<ul>', {class: 'root'}).appendTo(this.root)

const cats = this.kc.categories()

root.append(await Promise.all(
this.tree.filter((top) => top.category.index !== cats.get('index').index).map(async (top) => {
let e = $('<li>', {class: 'top', 'data-top-id': top.namespace.namespace[0]})
e.append(await this.dom.makeTitle(top))

if (top.category.index === cats.get('lang').index) {
this.processLangTop(top, e)
} else {
this.processTop(top, e)
}
return e
})
))
}

async processTop(top, e) {
Expand Down
2 changes: 2 additions & 0 deletions js/kunai/wand.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {NetworkError} from './error'
import {default as Numeral} from 'numeral'
import {Logger} from 'nagato'

import URL from 'url-parse'


class APIError extends NetworkError {
constructor() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"anser": "^1.4.4",
"babel-runtime": "^6.26.0",
"codemirror": "^5.31.0",
"crsearch": "^2.6.2",
"crsearch": "^2.6.4",
"font-awesome": "^4.7.0",
"jquery": "^3.2.1",
"marked": "^0.3.6",
Expand Down

0 comments on commit addd1e7

Please sign in to comment.