mirror of
https://github.com/klaussilveira/gitlist.git
synced 2025-11-17 19:20:56 +01:00
Added simple theming system
This commit is contained in:
1951
themes/bootstrap3/js/bootstrap.js
vendored
Normal file
1951
themes/bootstrap3/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
themes/bootstrap3/js/codemirror.js
Normal file
1
themes/bootstrap3/js/codemirror.js
Normal file
File diff suppressed because one or more lines are too long
3
themes/bootstrap3/js/html5.js
Executable file
3
themes/bootstrap3/js/html5.js
Executable file
@@ -0,0 +1,3 @@
|
||||
// HTML5 Shiv v3 | @jon_neal @afarkas @rem | MIT/GPL2 Licensed
|
||||
// Uncompressed source: https://github.com/aFarkas/html5shiv
|
||||
(function(a,b){function f(a){var c,d,e,f;b.documentMode>7?(c=b.createElement("font"),c.setAttribute("data-html5shiv",a.nodeName.toLowerCase())):c=b.createElement("shiv:"+a.nodeName);while(a.firstChild)c.appendChild(a.childNodes[0]);for(d=a.attributes,e=d.length,f=0;f<e;++f)d[f].specified&&c.setAttribute(d[f].nodeName,d[f].nodeValue);c.style.cssText=a.style.cssText,a.parentNode.replaceChild(c,a),c.originalElement=a}function g(a){var b=a.originalElement;while(a.childNodes.length)b.appendChild(a.childNodes[0]);a.parentNode.replaceChild(b,a)}function h(a,b){b=b||"all";var c=-1,d=[],e=a.length,f,g;while(++c<e){f=a[c],g=f.media||b;if(f.disabled||!/print|all/.test(g))continue;d.push(h(f.imports,g),f.cssText)}return d.join("")}function i(c){var d=new RegExp("(^|[\\s,{}])("+a.html5.elements.join("|")+")","gi"),e=c.split("{"),f=e.length,g=-1;while(++g<f)e[g]=e[g].split("}"),b.documentMode>7?e[g][e[g].length-1]=e[g][e[g].length-1].replace(d,'$1font[data-html5shiv="$2"]'):e[g][e[g].length-1]=e[g][e[g].length-1].replace(d,"$1shiv\\:$2"),e[g]=e[g].join("}");return e.join("{")}var c=function(a){return a.innerHTML="<x-element></x-element>",a.childNodes.length===1}(b.createElement("a")),d=function(a,b,c){return b.appendChild(a),(c=(c?c(a):a.currentStyle).display)&&b.removeChild(a)&&c==="block"}(b.createElement("nav"),b.documentElement,a.getComputedStyle),e={elements:"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),shivDocument:function(a){a=a||b;if(a.documentShived)return;a.documentShived=!0;var f=a.createElement,g=a.createDocumentFragment,h=a.getElementsByTagName("head")[0],i=function(a){f(a)};c||(e.elements.join(" ").replace(/\w+/g,i),a.createElement=function(a){var b=f(a);return b.canHaveChildren&&e.shivDocument(b.document),b},a.createDocumentFragment=function(){return e.shivDocument(g())});if(!d&&h){var j=f("div");j.innerHTML=["x<style>","article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}","audio{display:none}","canvas,video{display:inline-block;*display:inline;*zoom:1}","[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}","mark{background:#FF0;color:#000}","</style>"].join(""),h.insertBefore(j.lastChild,h.firstChild)}return a}};e.shivDocument(b),a.html5=e;if(c||!a.attachEvent)return;a.attachEvent("onbeforeprint",function(){if(a.html5.supportsXElement||!b.namespaces)return;b.namespaces.shiv||b.namespaces.add("shiv");var c=-1,d=new RegExp("^("+a.html5.elements.join("|")+")$","i"),e=b.getElementsByTagName("*"),g=e.length,j,k=i(h(function(a,b){var c=[],d=a.length;while(d)c.unshift(a[--d]);d=b.length;while(d)c.unshift(b[--d]);c.sort(function(a,b){return a.sourceIndex-b.sourceIndex}),d=c.length;while(d)c[--d]=c[d].styleSheet;return c}(b.getElementsByTagName("style"),b.getElementsByTagName("link"))));while(++c<g)j=e[c],d.test(j.nodeName)&&f(j);b.appendChild(b._shivedStyleSheet=b.createElement("style")).styleSheet.cssText=k}),a.attachEvent("onafterprint",function(){if(a.html5.supportsXElement||!b.namespaces)return;var c=-1,d=b.getElementsByTagName("*"),e=d.length,f;while(++c<e)f=d[c],f.originalElement&&g(f);b._shivedStyleSheet&&b._shivedStyleSheet.parentNode.removeChild(b._shivedStyleSheet)})})(this,document)
|
||||
4
themes/bootstrap3/js/jquery.js
vendored
Executable file
4
themes/bootstrap3/js/jquery.js
vendored
Executable file
File diff suppressed because one or more lines are too long
43
themes/bootstrap3/js/main.js
Executable file
43
themes/bootstrap3/js/main.js
Executable file
@@ -0,0 +1,43 @@
|
||||
$(function () {
|
||||
$('.dropdown-toggle').dropdown();
|
||||
|
||||
if ($('#sourcecode').length) {
|
||||
var value = $('#sourcecode').text();
|
||||
var mode = $('#sourcecode').attr('language');
|
||||
var pre = $('#sourcecode').get(0);
|
||||
var viewer = CodeMirror(function(elt) {
|
||||
pre.parentNode.replaceChild(elt, pre);
|
||||
}, {
|
||||
value: value,
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
lineWrapping: true,
|
||||
readOnly: true,
|
||||
mode: mode,
|
||||
lineNumberFormatter: function(ln) {
|
||||
return '<a name="L'+ ln +'"></a><a href="#L'+ ln +'">'+ ln +'</a>';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($('#md-content').length) {
|
||||
var converter = new Showdown.converter({extensions: ['table']});
|
||||
$('#md-content').html(converter.makeHtml($('#md-content').text()));
|
||||
}
|
||||
|
||||
function paginate() {
|
||||
var $pager = $('.pager');
|
||||
|
||||
$pager.find('.next a').one('click', function (e) {
|
||||
e.preventDefault();
|
||||
$.get(this.href, function (html) {
|
||||
$pager.after(html);
|
||||
$pager.remove();
|
||||
paginate();
|
||||
});
|
||||
});
|
||||
|
||||
$pager.find('.previous').remove();
|
||||
}
|
||||
paginate();
|
||||
});
|
||||
581
themes/bootstrap3/js/networkGraph.js
Normal file
581
themes/bootstrap3/js/networkGraph.js
Normal file
@@ -0,0 +1,581 @@
|
||||
/**
|
||||
* Network Graph JS
|
||||
* This File is a part of the GitList Project at http://gitlist.org
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php
|
||||
* @author Lukas Domnick <lukx@lukx.de> http://github.com/lukx
|
||||
*/
|
||||
|
||||
( function( $ ){
|
||||
// global config
|
||||
var cfg = {
|
||||
laneColors: ['#ff0000', '#0000FF', '#00FFFF', '#00FF00', '#FFFF00', '#ff00ff'],
|
||||
laneHeight: 20,
|
||||
columnWidth: 42,
|
||||
dotRadius: 3
|
||||
};
|
||||
|
||||
// Define the jQuery Plugins
|
||||
|
||||
/**
|
||||
* DragScrollr is a custom made x/y-Drag Scroll Plugin for Gitlist
|
||||
*
|
||||
* TODO: Make this touch-scrollable
|
||||
*/
|
||||
$.fn.dragScrollr = function() {
|
||||
var lastX,
|
||||
lastY,
|
||||
hotZone = 200,
|
||||
container = this.first(),
|
||||
domElement = container[0]; // so basically container without the jQuery stuff
|
||||
|
||||
function handleMouseDown( evt ) {
|
||||
container.on('mousemove', handleMouseMove);
|
||||
container.on('mouseup', handleMouseUp);
|
||||
container.on('mouseleave', handleMouseUp);
|
||||
lastX = evt.pageX;
|
||||
lastY = evt.pageY;
|
||||
}
|
||||
|
||||
function handleMouseMove(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
// save the last scroll position to figure out whether the scroll event has entered the hot zone
|
||||
var lastScrollLeft = domElement.scrollLeft;
|
||||
domElement.scrollLeft = domElement.scrollLeft + lastX - evt.pageX;
|
||||
domElement.scrollTop = domElement.scrollTop + lastY - evt.pageY;
|
||||
|
||||
if( lastScrollLeft > hotZone && domElement.scrollLeft <= hotZone ) {
|
||||
container.trigger('enterHotZone');
|
||||
}
|
||||
|
||||
// when we move into the hot zone
|
||||
|
||||
lastX = evt.pageX;
|
||||
lastY = evt.pageY;
|
||||
}
|
||||
|
||||
function handleMouseUp(evt) {
|
||||
container.off('mousemove', handleMouseMove)
|
||||
.off('mouseup', handleMouseUp)
|
||||
.off('mouseleave', handleMouseUp);
|
||||
}
|
||||
|
||||
// now bind the initial event
|
||||
container.on('mousedown', handleMouseDown);
|
||||
|
||||
// return this instead of container, because of the .first() we applied - remember?
|
||||
return this;
|
||||
};
|
||||
|
||||
function graphLaneManager() {
|
||||
var that = {},
|
||||
occupiedLanes = [];
|
||||
|
||||
// "private" methods
|
||||
function findLaneNumberFor( commit ) {
|
||||
|
||||
if( commit.lane ) {
|
||||
// oh? we've already got a lane?
|
||||
return commit.lane.number;
|
||||
}
|
||||
|
||||
// find out which lane may draw our dot on. Start with a free one
|
||||
var laneNumber = findFreeLane();
|
||||
|
||||
// if the child is a merge, we need to figure out which lane we may render this commit on.
|
||||
// Rules are simple: A "parent" by the same author as the merge may render on the same line as the child
|
||||
// others take the next free lane.
|
||||
// furthermore, commits in a linear line of events may stay on the same lane, too
|
||||
if( commit.children.length > 0) {
|
||||
if( !commit.children[0].isMerge // linear ...
|
||||
|| ( commit.children[0].isMerge && commit.children[0].author.email === commit.author.email ) // same author
|
||||
) {
|
||||
laneNumber = commit.children[0].lane.number;
|
||||
}
|
||||
}
|
||||
|
||||
return laneNumber;
|
||||
}
|
||||
|
||||
function findFreeLane() {
|
||||
var i = 0;
|
||||
|
||||
while( true ) {
|
||||
// if an array index is not yet defined or set to false, the lane with that number is free.
|
||||
if( !occupiedLanes[i] ) {
|
||||
return i;
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
|
||||
that.occupy = function( lane ) {
|
||||
// make sure we work with lane numbers here
|
||||
if( typeof lane === 'object' ) {
|
||||
lane = lane.number;
|
||||
}
|
||||
|
||||
occupiedLanes[lane] = true;
|
||||
};
|
||||
|
||||
that.free = function( lane ) {
|
||||
// make sure we work with lane numbers here
|
||||
if( typeof lane === 'object' ) {
|
||||
lane = lane.number;
|
||||
}
|
||||
|
||||
occupiedLanes[lane] = false;
|
||||
};
|
||||
|
||||
that.getLaneForCommit = function( commit ) {
|
||||
// does this commit have a lane already?
|
||||
if( commit.lane ) return commit.lane;
|
||||
|
||||
var laneNumber = findLaneNumberFor( commit );
|
||||
return that.getLane( laneNumber );
|
||||
};
|
||||
|
||||
that.getLane = function(laneNumber) {
|
||||
return {
|
||||
'number': laneNumber,
|
||||
'centerY': ( laneNumber * cfg.laneHeight ) + (cfg.laneHeight/2),
|
||||
'color': cfg.laneColors[ laneNumber % cfg.laneColors.length ]
|
||||
};
|
||||
};
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
function commitDetailOverlay( ) {
|
||||
var that = {},
|
||||
el = $('<div class="network-commit-overlay"></div>'),
|
||||
imageDisplay = $('<img/>').appendTo(el),
|
||||
messageDisplay = $('<h4></h4>').appendTo(el),
|
||||
metaDisplay = $('<p></p>').appendTo(el),
|
||||
authorDisplay = $('<a rel="author"></a>').appendTo(metaDisplay),
|
||||
dateDisplay = $('<span></span>').appendTo(metaDisplay),
|
||||
|
||||
commit;
|
||||
|
||||
el.hide();
|
||||
/**
|
||||
* Pads an input number with one leading '0' if needed, and assure it's a string
|
||||
*
|
||||
* @param input Number
|
||||
* @returns String
|
||||
*/
|
||||
function twoDigits( input ) {
|
||||
if( input < 10 ) {
|
||||
return '0' + input;
|
||||
}
|
||||
|
||||
return '' + input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a JS Native Date Object to a string, maintaining the same format given in the commit_list view
|
||||
* 'd/m/Y \\a\\t H:i:s'
|
||||
*
|
||||
* @param date Date
|
||||
* @returns String
|
||||
*/
|
||||
function getDateString( date ) {
|
||||
return twoDigits( date.getDate() ) + '/'
|
||||
+ twoDigits( date.getMonth() ) + '/'
|
||||
+ date.getFullYear() + ' at '
|
||||
+ twoDigits(date.getHours()) + ':'
|
||||
+ twoDigits(date.getMinutes()) + ':'
|
||||
+ twoDigits(date.getSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* update the author view
|
||||
*
|
||||
* @param author
|
||||
*/
|
||||
function setAuthor( author ) {
|
||||
authorDisplay.html(author.name)
|
||||
.attr('href', 'mailto:' + author.email );
|
||||
|
||||
imageDisplay.attr('src', author.image );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the commit that is being displayed in this detail overlay instance
|
||||
*
|
||||
* @param commit
|
||||
* @return that
|
||||
*/
|
||||
that.setCommit = function( commit ) {
|
||||
setAuthor( commit.author );
|
||||
dateDisplay.html( ' authored on ' + getDateString( commit.date ) );
|
||||
messageDisplay.html( commit.message );
|
||||
return that;
|
||||
};
|
||||
|
||||
// expose some jquery functions
|
||||
|
||||
that.show = function() {
|
||||
el.show();
|
||||
return that;
|
||||
};
|
||||
|
||||
that.hide = function() {
|
||||
el.hide();
|
||||
return that;
|
||||
};
|
||||
|
||||
that.appendTo = function(where) {
|
||||
el.appendTo(where);
|
||||
|
||||
return that;
|
||||
};
|
||||
|
||||
that.positionTo = function( x, y ) {
|
||||
el.css('left', x + 'px');
|
||||
el.css('top', y + 'px');
|
||||
};
|
||||
|
||||
that.outerWidth = function( ) {
|
||||
return el.outerWidth.apply(el, arguments);
|
||||
};
|
||||
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
function commitDataRetriever( startPage, callback ) {
|
||||
var that = {},
|
||||
nextPage = startPage,
|
||||
isLoading = false,
|
||||
indicatorElements;
|
||||
|
||||
that.updateIndicators = function() {
|
||||
if( isLoading ) {
|
||||
$(indicatorElements).addClass('loading-commits');
|
||||
} else {
|
||||
$(indicatorElements).removeClass('loading-commits');
|
||||
}
|
||||
};
|
||||
|
||||
that.bindIndicator = function( el ) {
|
||||
if( !indicatorElements ) {
|
||||
indicatorElements = $(el);
|
||||
} else {
|
||||
indicatorElements = indicatorElements.add(el);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
that.unbindIndicator = function( el ) {
|
||||
indicatorElements.not( el );
|
||||
};
|
||||
|
||||
function handleNetworkDataLoaded(data) {
|
||||
isLoading = false;
|
||||
that.updateIndicators();
|
||||
nextPage = data.nextPage;
|
||||
|
||||
if( !data.commits || data.commits.length === 0 ) {
|
||||
callback( null );
|
||||
}
|
||||
|
||||
callback(data.commits);
|
||||
}
|
||||
|
||||
function handleNetworkDataError() {
|
||||
throw "Network Data Error while retrieving Commits";
|
||||
}
|
||||
|
||||
that.retrieve = function() {
|
||||
|
||||
if( !nextPage ) {
|
||||
callback( null );
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
that.updateIndicators();
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: nextPage,
|
||||
success: handleNetworkDataLoaded,
|
||||
error: handleNetworkDataError
|
||||
});
|
||||
};
|
||||
|
||||
that.hasMore = function () {
|
||||
return ( !!nextPage );
|
||||
};
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
|
||||
// the $(document).ready starting point
|
||||
$( function() {
|
||||
|
||||
// initialise network graph only when there is one network graph container on the page
|
||||
if( $('div.network-graph').length !== 1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var
|
||||
// the element into which we will render our graph
|
||||
commitsGraph = $('div.network-graph').first(),
|
||||
laneManager = graphLaneManager(),
|
||||
dataRetriever = commitDataRetriever( commitsGraph.data('source'), handleCommitsRetrieved ),
|
||||
paper = Raphael( commitsGraph[0], commitsGraph.width(), commitsGraph.height()),
|
||||
usedColumns = 0,
|
||||
detailOverlay = commitDetailOverlay();
|
||||
|
||||
dataRetriever.bindIndicator( commitsGraph.parent('.network-view') );
|
||||
detailOverlay.appendTo( commitsGraph );
|
||||
|
||||
|
||||
function handleEnterHotZone() {
|
||||
dataRetriever.retrieve();
|
||||
}
|
||||
|
||||
function handleCommitsRetrieved( commits ) {
|
||||
|
||||
// no commits or empty commits array? Well, we can't draw a graph of that
|
||||
if( commits === null ) {
|
||||
handleNoAvailableData();
|
||||
return;
|
||||
}
|
||||
|
||||
prepareCommits( commits );
|
||||
renderCommits( commits );
|
||||
}
|
||||
|
||||
function handleNoAvailableData() {
|
||||
window.console && console.log('No (more) Data available');
|
||||
}
|
||||
|
||||
var awaitedParents = {};
|
||||
|
||||
function prepareCommits( commits ) {
|
||||
$.each( commits, function ( index, commit) {
|
||||
prepareCommit( commit );
|
||||
});
|
||||
}
|
||||
|
||||
function prepareCommit( commit ) {
|
||||
// make "date" an actual JS Date object
|
||||
commit.date = new Date(commit.date*1000);
|
||||
|
||||
// the parents will be filled once they have become prepared
|
||||
commit.parents = [];
|
||||
|
||||
// we will want to store this commit's children
|
||||
commit.children = getChildrenFor( commit );
|
||||
|
||||
commit.isFork = ( commit.children.length > 1 );
|
||||
commit.isMerge = ( commit.parentsHash.length > 1 );
|
||||
|
||||
// after a fork, the occupied lanes must be cleaned up. The children used some lanes we no longer occupy
|
||||
if ( commit.isFork === true ) {
|
||||
$.each( commit.children, function( key, thisChild ) {
|
||||
// free this lane
|
||||
laneManager.occupy( thisChild.lane );
|
||||
});
|
||||
}
|
||||
|
||||
commit.lane = laneManager.getLaneForCommit( commit );
|
||||
|
||||
// now the lane we chose must be marked occupied again.
|
||||
laneManager.occupy( commit.lane );
|
||||
|
||||
registerAwaitedParentsFor( commit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new childCommit to the dictionary of awaited parents
|
||||
*
|
||||
* @param commit who is waiting?
|
||||
*/
|
||||
function registerAwaitedParentsFor( commit ) {
|
||||
// This commit's parents are not yet known in our little world, as we are rendering following the time line.
|
||||
// Therefore we are registering this commit as "waiting" for each of the parent hashes
|
||||
$.each( commit.parentsHash, function( key, thisParentHash ) {
|
||||
// If awaitedParents does not already have a key for thisParent's hash, initialise as array
|
||||
if( !awaitedParents.hasOwnProperty(thisParentHash) ) {
|
||||
awaitedParents[thisParentHash] = [ commit ];
|
||||
} else {
|
||||
awaitedParents[ thisParentHash ].push( commit );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getChildrenFor( commit ) {
|
||||
var children = [];
|
||||
|
||||
if( awaitedParents.hasOwnProperty( commit.hash )) {
|
||||
// there are child commits waiting
|
||||
children = awaitedParents[ commit.hash ];
|
||||
|
||||
// let the children know their parent objects
|
||||
$.each( children, function(key, thisChild ) {
|
||||
thisChild.parents.push( commit );
|
||||
});
|
||||
|
||||
// remove this item from parentsBeingWaitedFor
|
||||
delete awaitedParents[ commit.hash ];
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
var lastRenderedDate = new Date(0);
|
||||
function renderCommits( commits ) {
|
||||
|
||||
var neededWidth = ((usedColumns + Object.keys(commits).length) * cfg.columnWidth);
|
||||
|
||||
if ( neededWidth > paper.width ) {
|
||||
extendPaper( neededWidth, paper.height );
|
||||
} else if( dataRetriever.hasMore() ) {
|
||||
// this is the case when we have not loaded enough commits to fill the paper yet. Get some more then...
|
||||
dataRetriever.retrieve();
|
||||
}
|
||||
|
||||
$.each( commits, function ( index, commit) {
|
||||
if( lastRenderedDate.getYear() !== commit.date.getYear()
|
||||
|| lastRenderedDate.getMonth() !== commit.date.getMonth()
|
||||
|| lastRenderedDate.getDate() !== commit.date.getDate() ) {
|
||||
// TODO: If desired, one could add a time scale on top, maybe.
|
||||
}
|
||||
renderCommit(commit);
|
||||
});
|
||||
}
|
||||
|
||||
function renderCommit( commit ) {
|
||||
// find the column this dot is drawn on
|
||||
usedColumns++;
|
||||
commit.column = usedColumns;
|
||||
|
||||
commit.dot = paper.circle( getXPositionForColumnNumber(commit.column), commit.lane.centerY, cfg.dotRadius );
|
||||
commit.dot.attr({
|
||||
fill: commit.lane.color,
|
||||
stroke: 'none',
|
||||
cursor: 'pointer'
|
||||
})
|
||||
.data('commit', commit)
|
||||
.mouseover( handleCommitMouseover )
|
||||
.mouseout( handleCommitMouseout )
|
||||
.click( handleCommitClick );
|
||||
|
||||
// maybe we have not enough space for the lane yet
|
||||
if( commit.lane.centerY + cfg.laneHeight > paper.height ) {
|
||||
extendPaper( paper.width, commit.lane.centerY + cfg.laneHeight )
|
||||
}
|
||||
|
||||
$.each( commit.children, function ( idx, thisChild ) {
|
||||
|
||||
// if there is one child only, stay on the commit's lane as long as possible when connecting the dots.
|
||||
// but if there is more than one child, switch to the child's lane ASAP.
|
||||
// this is to display merges and forks where they happen (ie. at a commit node/ a dot), rather than
|
||||
// connecting from a line.
|
||||
// So: commit.isFork decides whether or not we must switch lanes early
|
||||
|
||||
connectDots( commit, thisChild, commit.isFork );
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param firstCommit
|
||||
* @param secondCommit
|
||||
* @param switchLanesEarly (boolean): Move the line to the secondCommit's lane ASAP? Defaults to false
|
||||
*/
|
||||
function connectDots( firstCommit, secondCommit, switchLanesEarly ) {
|
||||
// default value for switchLanesEarly
|
||||
switchLanesEarly = switchLanesEarly || false;
|
||||
|
||||
var lineLane = switchLanesEarly ? secondCommit.lane : firstCommit.lane;
|
||||
|
||||
// the connection has 4 stops, resulting in the following 3 segments:
|
||||
// - from the x/y center of firstCommit.dot to the rightmost end (x) of the commit's column, with y=lineLane
|
||||
// - from the rightmost end of firstCommit's column, to the leftmost end of secondCommit's column
|
||||
// - from the leftmost end of secondCommit's column (y=lineLane) to the x/y center of secondCommit
|
||||
|
||||
paper.path(
|
||||
getSvgLineString(
|
||||
[firstCommit.dot.attr('cx'), firstCommit.dot.attr('cy')],
|
||||
[firstCommit.dot.attr('cx') + (cfg.columnWidth/2), lineLane.centerY],
|
||||
[secondCommit.dot.attr('cx') - (cfg.columnWidth/2), lineLane.centerY],
|
||||
[secondCommit.dot.attr('cx'), secondCommit.dot.attr('cy')]
|
||||
)
|
||||
).attr({ "stroke": lineLane.color, "stroke-width": 2 }).toBack();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// set together a path string from any amount of arguments
|
||||
// each argument is an array of [x, y] within the paper's coordinate system
|
||||
function getSvgLineString( ) {
|
||||
if (arguments.length < 2) return;
|
||||
|
||||
var svgString = 'M' + arguments[0][0] + ' ' + arguments[0][1];
|
||||
|
||||
for (var i = 1, j = arguments.length; i < j; i++){
|
||||
svgString += 'L' + arguments[i][0] + ' ' + arguments[i][1];
|
||||
}
|
||||
|
||||
return svgString;
|
||||
}
|
||||
|
||||
function handleCommitMouseover(evt) {
|
||||
detailOverlay.setCommit( this.data('commit'))
|
||||
.show();
|
||||
|
||||
var xPos = evt.pageX - commitsGraph.offset().left + commitsGraph.scrollLeft() - (detailOverlay.outerWidth()/2);
|
||||
// check that x doesn't run out the viewport
|
||||
xPos = Math.max( xPos, commitsGraph.scrollLeft() + 10);
|
||||
xPos = Math.min( xPos, commitsGraph.scrollLeft() + commitsGraph.width() - detailOverlay.outerWidth() - 10);
|
||||
|
||||
detailOverlay.positionTo( xPos,
|
||||
evt.pageY - commitsGraph.offset().top + commitsGraph.scrollTop() + 10);
|
||||
}
|
||||
|
||||
function handleCommitMouseout(evt) {
|
||||
detailOverlay.hide();
|
||||
}
|
||||
|
||||
function handleCommitClick( evt ) {
|
||||
window.open( this.data('commit').details );
|
||||
}
|
||||
|
||||
function getXPositionForColumnNumber( columnNumber ) {
|
||||
// we want the column's center point
|
||||
return ( paper.width - ( columnNumber * cfg.columnWidth ) + (cfg.columnWidth / 2 ));
|
||||
}
|
||||
|
||||
function extendPaper( newWidth, newHeight ) {
|
||||
var deltaX = newWidth - paper.width;
|
||||
|
||||
paper.setSize( newWidth, newHeight );
|
||||
// fixup parent's scroll position
|
||||
paper.canvas.parentNode.scrollLeft = paper.canvas.parentNode.scrollLeft + deltaX;
|
||||
|
||||
// now fixup the x positions of existing circles and lines
|
||||
paper.forEach( function( el ) {
|
||||
|
||||
if( el.type === "circle" ) {
|
||||
el.attr('cx', el.attr('cx') + deltaX);
|
||||
} else if ( el.type === "path") {
|
||||
var newXTranslation = el.data('currentXTranslation') || 0;
|
||||
newXTranslation += deltaX;
|
||||
el.transform( 't' + newXTranslation + ' 0' );
|
||||
el.data('currentXTranslation', newXTranslation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
commitsGraph.dragScrollr();
|
||||
commitsGraph.on('enterHotZone', handleEnterHotZone);
|
||||
// load initial data
|
||||
dataRetriever.retrieve( );
|
||||
});
|
||||
}( jQuery ));
|
||||
10
themes/bootstrap3/js/raphael.js
Normal file
10
themes/bootstrap3/js/raphael.js
Normal file
File diff suppressed because one or more lines are too long
1454
themes/bootstrap3/js/showdown.js
Normal file
1454
themes/bootstrap3/js/showdown.js
Normal file
File diff suppressed because it is too large
Load Diff
106
themes/bootstrap3/js/table.js
Normal file
106
themes/bootstrap3/js/table.js
Normal file
@@ -0,0 +1,106 @@
|
||||
/*global module:true*/
|
||||
/*
|
||||
* Basic table support with re-entrant parsing, where cell content
|
||||
* can also specify markdown.
|
||||
*
|
||||
* Tables
|
||||
* ======
|
||||
*
|
||||
* | Col 1 | Col 2 |
|
||||
* |======== |====================================================|
|
||||
* |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
|
||||
* | Plain | Value |
|
||||
*
|
||||
*/
|
||||
|
||||
(function(){
|
||||
var table = function(converter) {
|
||||
var tables = {}, style = 'text-align:left;', filter;
|
||||
tables.th = function(header){
|
||||
if (header.trim() === "") { return "";}
|
||||
var id = header.trim().replace(/ /g, '_').toLowerCase();
|
||||
return '<th id="' + id + '" style="'+style+'">' + header + '</th>';
|
||||
};
|
||||
tables.td = function(cell) {
|
||||
return '<td style="'+style+'">' + converter.makeHtml(cell) + '</td>';
|
||||
};
|
||||
tables.ths = function(){
|
||||
var out = "", i = 0, hs = [].slice.apply(arguments);
|
||||
for (i;i<hs.length;i+=1) {
|
||||
out += tables.th(hs[i]) + '\n';
|
||||
}
|
||||
return out;
|
||||
};
|
||||
tables.tds = function(){
|
||||
var out = "", i = 0, ds = [].slice.apply(arguments);
|
||||
for (i;i<ds.length;i+=1) {
|
||||
out += tables.td(ds[i]) + '\n';
|
||||
}
|
||||
return out;
|
||||
};
|
||||
tables.thead = function() {
|
||||
var out, i = 0, hs = [].slice.apply(arguments);
|
||||
out = "<thead>\n";
|
||||
out += "<tr>\n";
|
||||
out += tables.ths.apply(this, hs);
|
||||
out += "</tr>\n";
|
||||
out += "</thead>\n";
|
||||
return out;
|
||||
};
|
||||
tables.tr = function() {
|
||||
var out, i = 0, cs = [].slice.apply(arguments);
|
||||
out = "<tr>\n";
|
||||
out += tables.tds.apply(this, cs);
|
||||
out += "</tr>\n";
|
||||
return out;
|
||||
};
|
||||
filter = function(text) {
|
||||
var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = [];
|
||||
for (i; i<lines.length;i+=1) {
|
||||
line = lines[i];
|
||||
// looks like a table heading
|
||||
if (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
|
||||
line = line.trim();
|
||||
tbl.push('<table>');
|
||||
hs = line.substring(1, line.length -1).split('|');
|
||||
tbl.push(tables.thead.apply(this, hs));
|
||||
line = lines[++i];
|
||||
if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) {
|
||||
// not a table rolling back
|
||||
line = lines[--i];
|
||||
}
|
||||
else {
|
||||
line = lines[++i];
|
||||
tbl.push('<tbody>');
|
||||
while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
|
||||
line = line.trim();
|
||||
tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
|
||||
line = lines[++i];
|
||||
}
|
||||
tbl.push('</tbody>');
|
||||
tbl.push('</table>');
|
||||
// we are done with this table and we move along
|
||||
out.push(tbl.join('\n'));
|
||||
tbl = [];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
out.push(line);
|
||||
}
|
||||
return out.join('\n');
|
||||
};
|
||||
return [
|
||||
{
|
||||
type: 'lang',
|
||||
filter: filter
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
// Client-side export
|
||||
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; }
|
||||
// Server-side export
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = table;
|
||||
}
|
||||
}());
|
||||
Reference in New Issue
Block a user