commit
77282c0a52
|
@ -50,6 +50,9 @@ By default, Octotree only works on `github.com`. To support GitHub Enterprise on
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v1.7.2
|
||||||
|
* Fix bug long branches are not loaded correctly due to GitHub DOM change
|
||||||
|
|
||||||
### v1.7.1
|
### v1.7.1
|
||||||
* Fix space between tree and GitHub contents due to GitHub DOM change
|
* Fix space between tree and GitHub contents due to GitHub DOM change
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -7,12 +7,13 @@ const
|
||||||
'search', 'developer', 'account'
|
'search', 'developer', 'account'
|
||||||
]
|
]
|
||||||
, GH_RESERVED_REPO_NAMES = ['followers', 'following', 'repositories']
|
, GH_RESERVED_REPO_NAMES = ['followers', 'following', 'repositories']
|
||||||
, GH_BRANCH_SEL = '[aria-label="Switch branches or tags"]'
|
|
||||||
, GH_404_SEL = '#parallax_wrapper'
|
, GH_404_SEL = '#parallax_wrapper'
|
||||||
, GH_PJAX_SEL = '#js-repo-pjax-container'
|
, GH_PJAX_SEL = '#js-repo-pjax-container'
|
||||||
, GH_CONTAINERS = '.container'
|
, GH_CONTAINERS = '.container'
|
||||||
|
|
||||||
function GitHub() {
|
function GitHub() {
|
||||||
|
this._defaultBranch = {}
|
||||||
|
|
||||||
if (!window.MutationObserver) return
|
if (!window.MutationObserver) return
|
||||||
|
|
||||||
// Fix #151 by detecting when page layout is updated.
|
// Fix #151 by detecting when page layout is updated.
|
||||||
|
@ -36,24 +37,9 @@ function GitHub() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects a submodule.
|
* Selects a file.
|
||||||
*/
|
* @param {String} path - the file path.
|
||||||
GitHub.prototype.selectSubmodule = function(path) {
|
* @param {Number} tabSize - the tab size to use.
|
||||||
window.location.href = path
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downloads the file at the given
|
|
||||||
*/
|
|
||||||
GitHub.prototype.downloadFile = function(path, fileName) {
|
|
||||||
var link = document.createElement('a')
|
|
||||||
link.setAttribute('href', path.replace(/\/blob\//, '/raw/'))
|
|
||||||
link.setAttribute('download', fileName)
|
|
||||||
link.click()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Selects a path.
|
|
||||||
*/
|
*/
|
||||||
GitHub.prototype.selectFile = function(path, tabSize) {
|
GitHub.prototype.selectFile = function(path, tabSize) {
|
||||||
var container = $(GH_PJAX_SEL)
|
var container = $(GH_PJAX_SEL)
|
||||||
|
@ -69,8 +55,30 @@ GitHub.prototype.selectFile = function(path, tabSize) {
|
||||||
else window.location.href = path + qs // falls back if no container (i.e. GitHub DOM has changed or is not yet available)
|
else window.location.href = path + qs // falls back if no container (i.e. GitHub DOM has changed or is not yet available)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a file
|
||||||
|
* @param {String} path - the file path.
|
||||||
|
* @param {String} fileName - the file name.
|
||||||
|
*/
|
||||||
|
GitHub.prototype.downloadFile = function(path, fileName) {
|
||||||
|
var link = document.createElement('a')
|
||||||
|
link.setAttribute('href', path.replace(/\/blob\//, '/raw/'))
|
||||||
|
link.setAttribute('download', fileName)
|
||||||
|
link.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects a submodule
|
||||||
|
* @param {String} path - the submodule path.
|
||||||
|
*/
|
||||||
|
GitHub.prototype.selectSubmodule = function(path) {
|
||||||
|
window.location.href = path
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates page layout based on visibility status and width of the Octotree sidebar.
|
* Updates page layout based on visibility status and width of the Octotree sidebar.
|
||||||
|
* @param {Boolean} sidebarVisible - current visibility of the sidebar.
|
||||||
|
* @param {Number} sidebarWidth - current width of the sidebar.
|
||||||
*/
|
*/
|
||||||
GitHub.prototype.updateLayout = function(sidebarVisible, sidebarWidth) {
|
GitHub.prototype.updateLayout = function(sidebarVisible, sidebarWidth) {
|
||||||
var $containers = $(GH_CONTAINERS)
|
var $containers = $(GH_CONTAINERS)
|
||||||
|
@ -89,50 +97,83 @@ GitHub.prototype.updateLayout = function(sidebarVisible, sidebarWidth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the repository information if user is at a repository URL. Returns `null` otherwise.
|
* Retrieves the repository info at the current location.
|
||||||
|
* @param {Boolean} showInNonCodePage - if false, should not return data in non-code pages.
|
||||||
|
* @param {Object} currentRepo - current repo being shown by Octotree.
|
||||||
|
* @param {String} token - the personal access token.
|
||||||
|
* @param {Function} cb - the callback function.
|
||||||
*/
|
*/
|
||||||
GitHub.prototype.getRepoFromPath = function(showInNonCodePage, currentRepo) {
|
GitHub.prototype.getRepoFromPath = function(showInNonCodePage, currentRepo, token, cb) {
|
||||||
|
|
||||||
// 404 page, skip
|
// 404 page, skip
|
||||||
if ($(GH_404_SEL).length) return false
|
if ($(GH_404_SEL).length) {
|
||||||
|
return cb()
|
||||||
|
}
|
||||||
|
|
||||||
// (username)/(reponame)[/(type)]
|
// (username)/(reponame)[/(type)]
|
||||||
var match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?/)
|
var match = window.location.pathname.match(/([^\/]+)\/([^\/]+)(?:\/([^\/]+))?/)
|
||||||
if (!match) return false
|
if (!match) {
|
||||||
|
return cb()
|
||||||
|
}
|
||||||
|
|
||||||
|
var username = match[1]
|
||||||
|
var reponame = match[2]
|
||||||
|
|
||||||
// not a repository, skip
|
// not a repository, skip
|
||||||
if (~GH_RESERVED_USER_NAMES.indexOf(match[1])) return false
|
if (~GH_RESERVED_USER_NAMES.indexOf(username) ||
|
||||||
if (~GH_RESERVED_REPO_NAMES.indexOf(match[2])) return false
|
~GH_RESERVED_REPO_NAMES.indexOf(reponame)) {
|
||||||
|
return cb()
|
||||||
|
}
|
||||||
|
|
||||||
// skip non-code page unless showInNonCodePage is true
|
// skip non-code page unless showInNonCodePage is true
|
||||||
if (!showInNonCodePage && match[3] && !~['tree', 'blob'].indexOf(match[3])) return false
|
if (!showInNonCodePage && match[3] && !~['tree', 'blob'].indexOf(match[3])) {
|
||||||
|
return cb()
|
||||||
|
}
|
||||||
|
|
||||||
// get branch by inspecting page, quite fragile so provide multiple fallbacks
|
// get branch by inspecting page, quite fragile so provide multiple fallbacks
|
||||||
var branch =
|
var GH_BRANCH_SEL_1 = '[aria-label="Switch branches or tags"]'
|
||||||
$(GH_BRANCH_SEL).data('ref') ||
|
var GH_BRANCH_SEL_2 = '.repo-root a[data-branch]'
|
||||||
$(GH_BRANCH_SEL).children('.js-select-button').text() ||
|
var GH_BRANCH_SEL_3 = '.repository-sidebar a[aria-label="Code"]'
|
||||||
(currentRepo.username === match[1] && currentRepo.reponame === match[2] && currentRepo.branch) ||
|
|
||||||
'master'
|
|
||||||
|
|
||||||
return {
|
var branch =
|
||||||
username : match[1],
|
// Code page
|
||||||
reponame : match[2],
|
$(GH_BRANCH_SEL_1).attr('title') || $(GH_BRANCH_SEL_2).data('branch') ||
|
||||||
branch : branch
|
// Non-code page
|
||||||
|
($(GH_BRANCH_SEL_3).attr('href') || '').match(/([^\/]+)/g)[3] ||
|
||||||
|
// Assume same with previously
|
||||||
|
(currentRepo.username === username && currentRepo.reponame === reponame && currentRepo.branch) ||
|
||||||
|
// Default from cache
|
||||||
|
this._defaultBranch[username + '/' + reponame]
|
||||||
|
|
||||||
|
var repo = {username: username, reponame: reponame, branch: branch}
|
||||||
|
|
||||||
|
if (repo.branch) {
|
||||||
|
cb(null, repo)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._get(repo, null, token, function (err, data) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
repo.branch = this._defaultBranch[username + '/' + reponame] = data.default_branch || 'master'
|
||||||
|
cb(null, repo)
|
||||||
|
}.bind(this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches data of a particular repository.
|
* Retrieves the code tree of a repository.
|
||||||
* @param opts: { repo: repository, token (optional): user access token, apiUrl (optional): base API URL }
|
* @param {Object} opts: { repo: repository, node(optional): selected node (null for resursively loading), token (optional): user access token, apiUrl (optional): base API URL }
|
||||||
* @param cb(err: error, tree: array (of arrays) of items)
|
* @param {Function} cb(err: error, tree: array (of arrays) of items)
|
||||||
*/
|
*/
|
||||||
GitHub.prototype.fetchData = function(opts, cb) {
|
GitHub.prototype.getCodeTree = function(opts, cb) {
|
||||||
var self = this
|
var self = this
|
||||||
, repo = opts.repo
|
|
||||||
, folders = { '': [] }
|
, folders = { '': [] }
|
||||||
|
, repo = opts.repo
|
||||||
|
, token = opts.token
|
||||||
, encodedBranch = encodeURIComponent(decodeURIComponent(repo.branch))
|
, encodedBranch = encodeURIComponent(decodeURIComponent(repo.branch))
|
||||||
, $dummyDiv = $('<div/>')
|
, $dummyDiv = $('<div/>')
|
||||||
|
|
||||||
getTree(encodedBranch + '?recursive=true', function(err, tree) {
|
var treePath = (opts.node && (opts.node.sha || encodedBranch)) || (encodedBranch + '?recursive=1')
|
||||||
|
getTree(treePath, function(err, tree) {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
|
|
||||||
fetchSubmodules(function(err, submodules) {
|
fetchSubmodules(function(err, submodules) {
|
||||||
|
@ -153,6 +194,10 @@ GitHub.prototype.fetchData = function(opts, cb) {
|
||||||
// we're done
|
// we're done
|
||||||
if (item === undefined) return cb(null, folders[''])
|
if (item === undefined) return cb(null, folders[''])
|
||||||
|
|
||||||
|
// includes parent path
|
||||||
|
if (opts.node && opts.node.path)
|
||||||
|
item.path = opts.node.path + '/' + item.path
|
||||||
|
|
||||||
path = item.path
|
path = item.path
|
||||||
type = item.type
|
type = item.type
|
||||||
index = path.lastIndexOf('/')
|
index = path.lastIndexOf('/')
|
||||||
|
@ -162,10 +207,16 @@ GitHub.prototype.fetchData = function(opts, cb) {
|
||||||
item.text = name
|
item.text = name
|
||||||
item.icon = type // use `type` as class name for tree node
|
item.icon = type // use `type` as class name for tree node
|
||||||
|
|
||||||
|
if (opts.node) {
|
||||||
|
// no hierarchy in lazy loading
|
||||||
|
folders[''].push(item)
|
||||||
|
}
|
||||||
|
else
|
||||||
folders[path.substring(0, index)].push(item)
|
folders[path.substring(0, index)].push(item)
|
||||||
|
|
||||||
if (type === 'tree') {
|
if (type === 'tree') {
|
||||||
folders[item.path] = item.children = []
|
if (opts.node) item.children = true
|
||||||
|
else folders[item.path] = item.children = []
|
||||||
item.a_attr = { href: '#' }
|
item.a_attr = { href: '#' }
|
||||||
}
|
}
|
||||||
else if (type === 'blob') {
|
else if (type === 'blob') {
|
||||||
|
@ -206,26 +257,29 @@ GitHub.prototype.fetchData = function(opts, cb) {
|
||||||
})
|
})
|
||||||
|
|
||||||
function getTree(tree, cb) {
|
function getTree(tree, cb) {
|
||||||
get('/git/trees/' + tree, function(err, res) {
|
self._get(repo, '/git/trees/' + tree, token, function(err, res) {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
cb(null, res.tree)
|
cb(null, res.tree)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlob(sha, cb) {
|
function getBlob(sha, cb) {
|
||||||
get('/git/blobs/' + sha, function(err, res) {
|
self._get(repo, '/git/blobs/' + sha, token, function(err, res) {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
cb(null, atob(res.content.replace(/\n/g,'')))
|
cb(null, atob(res.content.replace(/\n/g,'')))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function get(path, cb) {
|
GitHub.prototype._get = function(repo, path, token, cb) {
|
||||||
var token = opts.token
|
var host = (location.host === 'github.com' ? 'api.github.com' : (location.host + '/api/v3'))
|
||||||
, host = (location.host === 'github.com' ? 'api.github.com' : (location.host + '/api/v3'))
|
|
||||||
, base = location.protocol + '//' + host + '/repos/' + repo.username + '/' + repo.reponame
|
, base = location.protocol + '//' + host + '/repos/' + repo.username + '/' + repo.reponame
|
||||||
, cfg = { method: 'GET', url: base + path, cache: false }
|
, cfg = { method: 'GET', url: base + (path || ''), cache: false }
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
cfg.headers = { Authorization: 'token ' + token }
|
||||||
|
}
|
||||||
|
|
||||||
if (token) cfg.headers = { Authorization: 'token ' + token }
|
|
||||||
$.ajax(cfg)
|
$.ajax(cfg)
|
||||||
.done(function(data) {
|
.done(function(data) {
|
||||||
cb(null, data)
|
cb(null, data)
|
||||||
|
@ -280,5 +334,4 @@ GitHub.prototype.fetchData = function(opts, cb) {
|
||||||
needAuth : needAuth,
|
needAuth : needAuth,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Octotree",
|
"name": "Octotree",
|
||||||
"version": "1.7.1",
|
"version": "2.0.0",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"author": "Buu Nguyen",
|
"author": "Buu Nguyen",
|
||||||
"description": "Display GitHub code in tree format",
|
"description": "Display GitHub code in tree format",
|
||||||
|
|
|
@ -7,6 +7,7 @@ const
|
||||||
TABSIZE : 'octotree.tabsize',
|
TABSIZE : 'octotree.tabsize',
|
||||||
REMEMBER : 'octotree.remember',
|
REMEMBER : 'octotree.remember',
|
||||||
LAZYLOAD : 'octotree.lazyload',
|
LAZYLOAD : 'octotree.lazyload',
|
||||||
|
RECURSIVE : 'octotree.recursive',
|
||||||
HOTKEYS : 'octotree.hotkeys',
|
HOTKEYS : 'octotree.hotkeys',
|
||||||
GHEURLS : 'octotree.gheurls',
|
GHEURLS : 'octotree.gheurls',
|
||||||
WIDTH : 'octotree.sidebar_width',
|
WIDTH : 'octotree.sidebar_width',
|
||||||
|
@ -21,6 +22,7 @@ const
|
||||||
TABSIZE : '',
|
TABSIZE : '',
|
||||||
REMEMBER : false,
|
REMEMBER : false,
|
||||||
LAZYLOAD : false,
|
LAZYLOAD : false,
|
||||||
|
RECURSIVE: true,
|
||||||
// @ifdef SAFARI
|
// @ifdef SAFARI
|
||||||
HOTKEYS : '⌘+b, ⌃+b',
|
HOTKEYS : '⌘+b, ⌃+b',
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -43,4 +45,5 @@ const
|
||||||
OPTS_CHANGE : 'octotree:change',
|
OPTS_CHANGE : 'octotree:change',
|
||||||
VIEW_READY : 'octotree:ready',
|
VIEW_READY : 'octotree:ready',
|
||||||
VIEW_CLOSE : 'octotree:close',
|
VIEW_CLOSE : 'octotree:close',
|
||||||
|
FETCH_ERROR : 'octotree:error'
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@
|
||||||
"icon": "data/icons/icon48.png",
|
"icon": "data/icons/icon48.png",
|
||||||
"icon64": "data/icons/icon64.png",
|
"icon64": "data/icons/icon64.png",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "1.7.1",
|
"version": "2.0.0",
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"cross-domain-content": ["https://api.github.com", "https://github.com"]
|
"cross-domain-content": ["https://api.github.com", "https://github.com"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ $(document).ready(function() {
|
||||||
showView(hasError ? errorView.$view : treeView.$view)
|
showView(hasError ? errorView.$view : treeView.$view)
|
||||||
})
|
})
|
||||||
.on(EVENT.OPTS_CHANGE, optionsChanged)
|
.on(EVENT.OPTS_CHANGE, optionsChanged)
|
||||||
|
.on(EVENT.FETCH_ERROR, function(event, err) {
|
||||||
|
errorView.show(err)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
$document
|
$document
|
||||||
|
@ -81,6 +84,9 @@ $(document).ready(function() {
|
||||||
key.unbind(value[0])
|
key.unbind(value[0])
|
||||||
key(value[1], toggleSidebar)
|
key(value[1], toggleSidebar)
|
||||||
break
|
break
|
||||||
|
case STORE.RECURSIVE:
|
||||||
|
reload = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (reload) tryLoadRepo(true)
|
if (reload) tryLoadRepo(true)
|
||||||
|
@ -92,9 +98,12 @@ $(document).ready(function() {
|
||||||
, shown = store.get(STORE.SHOWN)
|
, shown = store.get(STORE.SHOWN)
|
||||||
, lazyload = store.get(STORE.LAZYLOAD)
|
, lazyload = store.get(STORE.LAZYLOAD)
|
||||||
, token = store.get(STORE.TOKEN)
|
, token = store.get(STORE.TOKEN)
|
||||||
, repo = adapter.getRepoFromPath(showInNonCodePage, currRepo)
|
|
||||||
|
|
||||||
if (repo) {
|
adapter.getRepoFromPath(showInNonCodePage, currRepo, token, function(err, repo) {
|
||||||
|
if (err) {
|
||||||
|
errorView.show(err)
|
||||||
|
}
|
||||||
|
else if (repo) {
|
||||||
$toggler.show()
|
$toggler.show()
|
||||||
helpPopup.show()
|
helpPopup.show()
|
||||||
|
|
||||||
|
@ -105,12 +114,9 @@ $(document).ready(function() {
|
||||||
if (repoChanged || reload === true) {
|
if (repoChanged || reload === true) {
|
||||||
$document.trigger(EVENT.REQ_START)
|
$document.trigger(EVENT.REQ_START)
|
||||||
currRepo = repo
|
currRepo = repo
|
||||||
treeView.showHeader(repo)
|
|
||||||
|
|
||||||
adapter.fetchData({ repo: repo, token: token }, function(err, tree) {
|
treeView.showHeader(repo)
|
||||||
if (err) errorView.show(err)
|
treeView.show(repo, token)
|
||||||
else treeView.show(repo, tree)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
else treeView.syncSelection()
|
else treeView.syncSelection()
|
||||||
}
|
}
|
||||||
|
@ -119,6 +125,7 @@ $(document).ready(function() {
|
||||||
$toggler.hide()
|
$toggler.hide()
|
||||||
toggleSidebar(false)
|
toggleSidebar(false)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function showView(view) {
|
function showView(view) {
|
||||||
|
|
|
@ -202,6 +202,11 @@
|
||||||
label {
|
label {
|
||||||
font-weight: normal !important;
|
font-weight: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label.disabled {
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=text], textarea {
|
input[type=text], textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.7.1</string>
|
<string>2.0.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.7.1</string>
|
<string>2.0.0</string>
|
||||||
<key>Chrome</key>
|
<key>Chrome</key>
|
||||||
<dict/>
|
<dict/>
|
||||||
<key>Content</key>
|
<key>Content</key>
|
||||||
|
|
|
@ -53,7 +53,10 @@
|
||||||
<label><input type="checkbox" data-store="LAZYLOAD"> Only load tree when sidebar is open</label>
|
<label><input type="checkbox" data-store="LAZYLOAD"> Only load tree when sidebar is open</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label><input type="checkbox" data-store="COLLAPSE"> Collapse folders with single sub-folder</label>
|
<label><input type="checkbox" data-store="RECURSIVE"> Load repository recursively</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label><input type="checkbox" data-store="COLLAPSE" data-trigger-disable="RECURSIVE"> Collapse folders with single sub-folder</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// When navigating from non-code pages (i.e. Pulls, Issues) to code page
|
// When navigating from non-code pages (i.e. Pulls, Issues) to code page
|
||||||
// GitHub doesn't reload the page but uses pjax. Need to detect and load Octotree.
|
// GitHub doesn't reload the page but uses pjax. Need to detect and load Octotree.
|
||||||
var href, hash
|
var firstLoad = true, href, hash
|
||||||
function detectLocationChange() {
|
function detectLocationChange() {
|
||||||
if (location.href !== href || location.hash !== hash) {
|
if (location.href !== href || location.hash !== hash) {
|
||||||
href = location.href
|
href = location.href
|
||||||
hash = location.hash
|
hash = location.hash
|
||||||
$(document).trigger(EVENT.LOC_CHANGE, href, hash)
|
|
||||||
|
// If this is the first time this is called, no need to notify change as
|
||||||
|
// Octotree does its own initialization after loading options.
|
||||||
|
if (firstLoad) {
|
||||||
|
firstLoad = false
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
setTimeout(function () {
|
||||||
|
$(document).trigger(EVENT.LOC_CHANGE, href, hash)
|
||||||
|
}, 200) // Waits a bit for pjax DOM change
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(detectLocationChange, 200)
|
setTimeout(detectLocationChange, 200)
|
||||||
}
|
}
|
||||||
detectLocationChange()
|
detectLocationChange()
|
||||||
|
|
|
@ -6,6 +6,23 @@ function OptionsView($dom, store) {
|
||||||
|
|
||||||
this.$view = $view
|
this.$view = $view
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
function triggerChange(checkbox) {
|
||||||
|
var store = $(checkbox).data('store')
|
||||||
|
, checkboxs = $view.find('[data-trigger-disable=' + store + ']')
|
||||||
|
checkboxs.prop('disabled', !checkbox.checked).closest('label').toggleClass('disabled', !checkbox.checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
eachOption(
|
||||||
|
function($elm) {
|
||||||
|
// triggers to disable all checkboxs having data-trigger-disable
|
||||||
|
$elm.change(function(event) {
|
||||||
|
triggerChange(event.target)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
// hide options view when sidebar is hidden
|
// hide options view when sidebar is hidden
|
||||||
$(document).on(EVENT.TOGGLE, function(event, visible) {
|
$(document).on(EVENT.TOGGLE, function(event, visible) {
|
||||||
if (!visible) toggle(false)
|
if (!visible) toggle(false)
|
||||||
|
@ -23,7 +40,8 @@ function OptionsView($dom, store) {
|
||||||
else {
|
else {
|
||||||
eachOption(
|
eachOption(
|
||||||
function($elm, key, local, value, cb) {
|
function($elm, key, local, value, cb) {
|
||||||
if ($elm.is(':checkbox')) $elm.prop('checked', value)
|
// Original jQuery prop function doesn't trigger change event
|
||||||
|
if ($elm.is(':checkbox')) $elm.prop('checked', value).trigger("change")
|
||||||
else $elm.val(value)
|
else $elm.val(value)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,15 +74,30 @@ TreeView.prototype.showHeader = function(repo) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeView.prototype.show = function(repo, treeData) {
|
TreeView.prototype.show = function(repo, token) {
|
||||||
var self = this
|
var self = this
|
||||||
, treeContainer = self.$view.find('.octotree_view_body')
|
, treeContainer = self.$view.find('.octotree_view_body')
|
||||||
, tree = treeContainer.jstree(true)
|
, tree = treeContainer.jstree(true)
|
||||||
, collapseTree = self.store.get(STORE.COLLAPSE)
|
, collapseTree = self.store.get(STORE.COLLAPSE)
|
||||||
|
, recursiveLoad = self.store.get(STORE.RECURSIVE)
|
||||||
|
|
||||||
|
function fetchData(node, success) {
|
||||||
|
var selectedNode = node.original
|
||||||
|
if (node.id === '#') selectedNode = {path: ''}
|
||||||
|
self.adapter.getCodeTree({ repo: repo, token: token, node: recursiveLoad ? null : selectedNode}, function(err, treeData) {
|
||||||
|
if (err) $(self).trigger(EVENT.FETCH_ERROR, [err])
|
||||||
|
else success(treeData)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.settings.core.data = function (node, cb) {
|
||||||
|
fetchData(node, function(treeData) {
|
||||||
treeData = sort(treeData)
|
treeData = sort(treeData)
|
||||||
if (collapseTree) treeData = collapse(treeData)
|
if (collapseTree && recursiveLoad)
|
||||||
tree.settings.core.data = treeData
|
treeData = collapse(treeData)
|
||||||
|
cb(treeData)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
treeContainer.one('refresh.jstree', function() {
|
treeContainer.one('refresh.jstree', function() {
|
||||||
self.syncSelection()
|
self.syncSelection()
|
||||||
|
@ -97,7 +112,7 @@ TreeView.prototype.show = function(repo, treeData) {
|
||||||
return a.type === 'blob' ? 1 : -1
|
return a.type === 'blob' ? 1 : -1
|
||||||
})
|
})
|
||||||
folder.forEach(function(item) {
|
folder.forEach(function(item) {
|
||||||
if (item.type === 'tree') sort(item.children)
|
if (item.type === 'tree' && item.children !== true && item.children.length > 0) sort(item.children)
|
||||||
})
|
})
|
||||||
return folder
|
return folder
|
||||||
}
|
}
|
||||||
|
@ -119,17 +134,41 @@ TreeView.prototype.show = function(repo, treeData) {
|
||||||
|
|
||||||
TreeView.prototype.syncSelection = function() {
|
TreeView.prototype.syncSelection = function() {
|
||||||
var tree = this.$view.find('.octotree_view_body').jstree(true)
|
var tree = this.$view.find('.octotree_view_body').jstree(true)
|
||||||
, path = location.pathname
|
, path = decodeURIComponent(location.pathname)
|
||||||
|
, recursiveLoad = this.store.get(STORE.RECURSIVE)
|
||||||
|
|
||||||
if (!tree) return
|
if (!tree) return
|
||||||
tree.deselect_all()
|
|
||||||
|
|
||||||
// e.g. converts /buunguyen/octotree/type/branch/path to path
|
// e.g. converts /buunguyen/octotree/type/branch/path to path
|
||||||
var match = path.match(/(?:[^\/]+\/){4}(.*)/)
|
var match = path.match(/(?:[^\/]+\/){4}(.*)/)
|
||||||
, nodeId
|
if (!match) return
|
||||||
if (match) {
|
|
||||||
nodeId = PREFIX + decodeURIComponent(match[1])
|
currentPath = match[1]
|
||||||
tree.select_node(nodeId)
|
|
||||||
tree.open_node(nodeId)
|
// e.g. converts ["lib/controllers"] to ["lib", "lib/controllers"]
|
||||||
|
function createPaths(fullPath) {
|
||||||
|
var paths = fullPath.split("/")
|
||||||
|
, arrResult = [paths[0]]
|
||||||
|
|
||||||
|
paths.reduce(function(lastPath, curPath) {
|
||||||
|
var path = (lastPath + "/" + curPath)
|
||||||
|
arrResult.push(path)
|
||||||
|
return path
|
||||||
|
})
|
||||||
|
return arrResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openPathAtIndex (paths, index) {
|
||||||
|
nodeId = PREFIX + paths[index]
|
||||||
|
if (tree.get_node(nodeId)) {
|
||||||
|
tree.deselect_all()
|
||||||
|
tree.select_node(nodeId)
|
||||||
|
tree.open_node(nodeId, function(node){
|
||||||
|
if (index < paths.length - 1) openPathAtIndex(paths, index + 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var paths = recursiveLoad ? [currentPath] : createPaths(currentPath)
|
||||||
|
openPathAtIndex(paths, 0)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue