Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

現在ページに特化したUX改善集 #48

Merged
merged 2 commits into from
Nov 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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