Jason.ji has submitted this change and it was merged.
Change subject: - Add support for starting a VIKI graph with categories as well
as page titles. - Minimize the number of redraws on initial graph population
and elaboration by restructuring how initial graph population works; added a
warning if too many nodes are startin
......................................................................
- Add support for starting a VIKI graph with categories as well as page titles.
- Minimize the number of redraws on initial graph population and elaboration by
restructuring how initial graph population works; added a warning if too many
nodes are starting a graph.
Change-Id: Iaa0fb28e8330bc2c0fa99a673987da5f98b37535
---
M VIKI.css
M VIKI.js
M VIKI.php
3 files changed, 386 insertions(+), 241 deletions(-)
Approvals:
Jason.ji: Verified; Looks good to me, approved
jenkins-bot: Verified
diff --git a/VIKI.css b/VIKI.css
index 0f5769d..7686079 100644
--- a/VIKI.css
+++ b/VIKI.css
@@ -58,7 +58,7 @@
overflow: auto !important;
}
-#progressbarDiv .ui-progressbar-value.ui-widget-header {
- background: blue;
+.progressbarDiv .ui-progressbar-value.ui-widget-header {
+ background: blue !important;
height: 106% !important;
}
diff --git a/VIKI.js b/VIKI.js
index 207dc85..834953a 100644
--- a/VIKI.js
+++ b/VIKI.js
@@ -58,6 +58,9 @@
this.HIDE_HUB = 0;
this.HIDE_INCOMING = 1;
this.HIDE_OUTGOING = 2;
+ this.ELABORATION_TYPE_NORMAL = 0;
+ this.ELABORATION_TYPE_SECOND_ORDER_LINKS = 1;
+ this.ELABORATION_TYPE_INITIAL_POPULATION = 2;
/*
* Mutable Global Variables
@@ -93,6 +96,7 @@
this.ongoingElaborations = 0;
this.TempLinks = [];
this.TempHiddenLinks = [];
+ this.TempNodes = [];
this.OngoingElaborationNodes = [];
this.showSecondOrderLinks = false;
@@ -686,33 +690,69 @@
vex.close( self.loadingView.data().vex.id );
- this.ongoingElaborations =
self.initialPageTitles.length;
-
- for ( var i = 0; i < self.initialPageTitles.length; i++
) {
- var node = self.createWikiNodeFromWiki(
self.initialPageTitles[ i ], self.THIS_WIKI );
- self.addNode( node );
- self.visitNode( node, function(isHidden,
thisNode) {
- if( isHidden ) {
- self.elaborateWikiNode(
thisNode, function( thisNode ) {
- self.hideNodeAndRedraw(
thisNode );
- }, false );
- }
- else {
- self.elaborateWikiNode(
thisNode, null, false );
- }
- } );
+ var initialNodeCount = self.initialPageTitles.length;
+ var warningMessage;
+ if(initialNodeCount > 50) {
+ warningMessage = "You are about to start a
graph with "+initialNodeCount+" nodes and try to elaborate them all. \
+ The graph is unlikely to successfully handle
this number of nodes and may freeze or crash. This is not recommended. Are you
sure you want to continue?";
}
+ else if(initialNodeCount > 10) {
+ warningMessage = "You are about to start a
graph with "+initialNodeCount+" nodes and try to elaborate them all.\
+ This may take a very long time and result in a
sluggish graph. Are you sure you want to continue?";
+ }
+ else {
+ warningMessage = null;
+ }
+ if(warningMessage) {
+ self.showWarningDialog( warningMessage,
function() { startElaboratingNodes(); }, function() { });
+ }
+ else
+ startElaboratingNodes();
- self.Force.nodes( self.Nodes );
- self.Force.links( self.Links );
+ function startElaboratingNodes() {
+ self.ongoingElaborations =
self.initialPageTitles.length;
- self.redraw(true);
+ var nodesElaborated = 0, totalElaborateCount =
self.initialPageTitles.length, nodesToHide = [];
+ self.showProgressOverlay( "Elaborating initial
nodes... 0%", totalElaborateCount );
+ for ( var i = 0; i <
self.initialPageTitles.length; i++ ) {
+ var node = self.createWikiNodeFromWiki(
self.initialPageTitles[ i ], self.THIS_WIKI );
+ self.addNode( node );
+ self.visitNode( node,
function(isHidden, thisNode) {
+ if( isHidden ) {
+ nodesToHide.push(
thisNode );
+ }
+ self.elaborateWikiNode(
thisNode, function( thisNode ) {
+ nodesElaborated++;
+
self.updateProgressOverlay( "Elaborating initial nodes... "+ +(nodesElaborated
/ totalElaborateCount * 100).toPrecision(4) + "%", nodesElaborated );
+ if( nodesElaborated ==
totalElaborateCount ) {
+
self.closeProgressOverlay();
+
self.TempNodes.forEach(function(node) {
+
self.addNode(node);
+ });
+ self.TempNodes
= [];
- // after initial population, by default select the
first node.
- self.SelectedNodeIndex = 0;
- self.displayNodeInfo( self.Nodes[ 0 ] );
- self.redrawNode( self.Nodes[ 0 ] );
+
self.addTempLinksToGraph();
+
nodesToHide.forEach( function(node) {
+
self.hideNode( node, false );
+ } );
+
self.log("redraw() - from populateInitialGraph() after all elaborations
complete");
+ self.redraw(
true );
+ }
+ },
self.ELABORATION_TYPE_INITIAL_POPULATION );
+ } );
+ }
+
+ self.Force.nodes( self.Nodes );
+ self.Force.links( self.Links );
+ self.log("redraw() - from
populateInitialGraph()");
+ self.redraw(true);
+
+ // after initial population, by default select
the first node.
+ self.SelectedNodeIndex = 0;
+ self.displayNodeInfo( self.Nodes[ 0 ] );
+ self.redrawNode( self.Nodes[ 0 ] );
+ }
};
/*
@@ -759,6 +799,7 @@
newNodes.on( "contextmenu", function( d ) {
self.SelectedNodeIndex = d.index;
+ self.log("redraw() - from contextmenu");
self.redraw( false );
} );
@@ -1640,50 +1681,43 @@
my.VikiJS.prototype.findNode = function( property, value ) {
var self = this;
- var oldString, newString, newValue;
- for ( var i = 0; i < self.Nodes.length; i++ ) {
- if ( property === 'pageTitle' ) {
- // a specific check for page titles -
the first letter is case insensitive
- oldString = self.Nodes[ i ][ property ];
- if ( oldString ) {
- newString = self.replaceAt(
oldString, oldString.indexOf( ":" ) + 1,
- oldString.charAt(
oldString.indexOf( ":" ) + 1 )
- .toLowerCase() );
- newValue = self.replaceAt(
value, value.indexOf( ":" ) + 1,
- value.charAt(
value.indexOf( ":" ) + 1 )
- .toLowerCase() );
- if ( newString === newValue )
- return self.Nodes[ i ];
- }
- } else if ( typeof self.Nodes[ i ][ property ]
!== 'undefined' && self.Nodes[ i ][ property ] === value ) {
- return self.Nodes[ i ];
- }
- }
+ var ret = findInList( self.Nodes );
+ if(!ret)
+ ret = findInList( self.HiddenNodes );
+ if(!ret)
+ ret = findInList( self.TempNodes );
+ return ret;
- for ( i = 0; i < self.HiddenNodes.length; i++ ) {
- if ( property === 'pageTitle' ) {
- // a specific check for page titles -
the first letter is case insensitive
- oldString = self.HiddenNodes[ i ][
property ];
- if ( oldString ) {
- newString = self.replaceAt(
oldString, oldString.indexOf( ":" ) + 1, oldString.charAt( oldString.indexOf(
":" ) + 1 )
- .toLowerCase() );
- newValue = self.replaceAt(
value, value.indexOf( ":" ) + 1, value.charAt( value.indexOf( ":" ) + 1 )
- .toLowerCase() );
- if ( newString === newValue )
- return
self.HiddenNodes[ i ];
+ function findInList( list ) {
+ var oldString, newString, newValue;
+
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( property === 'pageTitle' ) {
+ // a specific check for page
titles - the first letter is case insensitive
+ oldString = list[ i ][ property
];
+ if ( oldString ) {
+ newString =
self.replaceAt( oldString, oldString.indexOf( ":" ) + 1,
+
oldString.charAt( oldString.indexOf( ":" ) + 1 )
+ .toLowerCase()
);
+ newValue =
self.replaceAt( value, value.indexOf( ":" ) + 1,
+ value.charAt(
value.indexOf( ":" ) + 1 )
+ .toLowerCase()
);
+ if ( newString ===
newValue )
+ return list[ i
];
+ }
+ } else if ( typeof list[ i ][ property
] !== 'undefined' && list[ i ][ property ] === value ) {
+ return list[ i ];
}
- } else if ( typeof self.HiddenNodes[ i ][
property ] !== 'undefined' && self.HiddenNodes[ i ][ property ] === value ) {
- return self.HiddenNodes[ i ];
}
+ return null;
}
- return null;
};
/**
* Add a new node to the graph.
*
- * This method is called internally when a newly created node
is to be added to the VIKI graph.
+ * This method is called internally when a newly created node
is added to the VIKI graph.
*
* @param {Object} node to be added to the graph.
*/
@@ -1731,6 +1765,17 @@
return link;
};
+ my.VikiJS.prototype.addTempLink = function( node1, node2 ) {
+ var self = this;
+ var link = {
+ source: node1,
+ target: node2,
+ bidirectional: false
+ };
+ self.TempLinks.push( link );
+ return link;
+ }
+
my.VikiJS.prototype.addSecondOrderLink = function( node1,
node2, hidden) {
var self = this;
@@ -1746,6 +1791,41 @@
self.TempLinks.push( link );
}
return link;
+ }
+
+ my.VikiJS.prototype.addTempLinksToGraph = function() {
+ for( var i = 0; i < self.TempLinks.length; i++ ) {
+ var link = self.TempLinks[ i ];
+ var alreadyFound = self.findLink(
link.source.identifier, link.target.identifier );
+ if( alreadyFound ) {
+ // If this link was found, check if
it's a duplicate (source and targets are same in both) or bidirectional (source
and targets are reversed)
+ if(link.source.identifier ===
alreadyFound.target.identifier && link.source.identifier ===
alreadyFound.target.identifier)
+ alreadyFound.bidirectional =
true;
+ continue;
+ }
+ self.Links.push( link );
+ self.LinkMap[ link.source.identifier + "," +
link.target.identifier ] = link;
+ self.LinkMap[ link.target.identifier + "," +
link.source.identifier ] = link;
+ }
+ self.TempLinks = [];
+ }
+
+ my.VikiJS.prototype.addHiddenLinksToGraph = function() {
+ for ( var i = 0; i < self.HiddenLinks.length; i++ ) {
+ var link = self.HiddenLinks[ i ];
+ var alreadyFound = self.findLink(
link.source.identifier, link.target.identifier );
+ if( alreadyFound ) {
+ // If this link was found, check if
it's a duplicate (source and targets are same in both) or bidirectional (source
and targets are reversed)
+ if(link.source.identifier ===
alreadyFound.target.identifier && link.source.identifier ===
alreadyFound.target.identifier)
+ alreadyFound.bidirectional =
true;
+ continue;
+ }
+ self.Links.push( link );
+ self.LinkMap[ link.source.identifier + "," +
link.target.identifier ] = link;
+ self.LinkMap[ link.target.identifier + "," +
link.source.identifier ] = link;
+ }
+
+ self.HiddenLinks = [];
}
/**
@@ -1803,7 +1883,7 @@
var node = self.Nodes[ index ];
if ( node.type === self.WIKI_PAGE_TYPE ) {
self.ongoingElaborations++;
- self.elaborateWikiNode( node, null, false );
+ self.elaborateWikiNode( node, null,
self.ELABORATION_TYPE_NORMAL );
}
};
@@ -1816,8 +1896,10 @@
* is called internally whenever the user chooses to elaborate
a node.
*
* @param {Object} node node to elaborate
+ * @param {Object} completionHandler code block to execute at
the end of elaboration
+ * @param {Integer} elaborationType type of elaboration:
normal, 2nd order links, initial population
*/
- my.VikiJS.prototype.elaborateWikiNode = function( node,
completionHandler, forSecondOrderLinks ) {
+ my.VikiJS.prototype.elaborateWikiNode = function( node,
completionHandler, elaborationType ) {
var self = this;
// 1. Get external links OUT from page.
@@ -1836,12 +1918,13 @@
},
success: function( data, textStatus, jqXHR ) {
externalElaborationData = data;
- checkElaborationQueriesComplete( node,
completionHandler, forSecondOrderLinks );
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
},
error: function() {
self.showError( mw.message(
'viki-error-external-links', node.pageTitle )
.text() );
externalElaborationData = {};
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
}
} );
@@ -1859,12 +1942,13 @@
},
success: function( data, textStatus, jqXHR ) {
intraOutElaborationData = data;
- checkElaborationQueriesComplete( node,
completionHandler, forSecondOrderLinks );
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
},
error: function() {
self.showError( mw.message(
'viki-error-intrawiki-out', node.pageTitle )
.text() );
intraOutElaborationData = {};
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
}
} );
// 3. Get intra-wiki links IN to this page.
@@ -1881,20 +1965,21 @@
},
success: function( data, textStatus, jqXHR ) {
intraInElaborationData = data;
- checkElaborationQueriesComplete( node,
completionHandler, forSecondOrderLinks );
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
},
error: function() {
self.showError( mw.message(
'viki-error-intrawiki-in', node.pageTitle )
.text() );
intraInElaborationData = {};
+ checkElaborationQueriesComplete( node,
completionHandler, elaborationType );
}
} );
- if( !forSecondOrderLinks ) {
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS ) {
node.elaborated = true;
self.displayNodeInfo( node );
}
- function checkElaborationQueriesComplete( originNode,
completionHandler, forSecondOrderLinks ) {
+ function checkElaborationQueriesComplete( originNode,
completionHandler, elaborationType ) {
if(externalElaborationData !== undefined &&
intraOutElaborationData !== undefined && intraInElaborationData !== undefined) {
var externalLinksList =
externalElaborationData.query.pages[ Object.keys(
externalElaborationData.query.pages )[ 0 ] ].extlinks;
var intraLinksOutList =
intraOutElaborationData.query.pages[ Object.keys(
intraOutElaborationData.query.pages )[ 0 ] ].links;
@@ -1906,32 +1991,16 @@
var sum = externalLinksCount +
intraLinksOutCount + intraLinksInCount;
- if(sum > 50 && !forSecondOrderLinks) {
- vex.dialog.buttons.YES.text =
'Yes';
- vex.dialog.buttons.NO.text =
'No';
-
- vex.dialog.confirm({
- css: {
- "position":
"absolute",
- "top" : "auto",
- "left" : "auto",
- "right" :
"auto",
- "bottom" :
"auto",
- "height" :
self.INITIAL_HEIGHT+"px",
- "width" :
self.INITIAL_WIDTH+"px"
- },
- appendLocation:
'#VIKI_'+self.ID+'_overlay',
- message: "About to add
"+sum+" nodes... this may take a very long time and result in a sluggish graph.
Are you sure you want to?",
- callback:
function(value) {
- if(value) {
-
completeElaboration();
- }
- else {
-
node.elaborated = false;
-
self.ongoingElaborations--;
- }
- }
- });
+ if(sum > 50 && elaborationType ===
self.ELABORATION_TYPE_NORMAL) {
+ self.showWarningDialog("About
to add "+sum+" nodes... this may take a very long time and result in a sluggish
graph. Are you sure you want to?",
+ function() {
+
completeElaboration();
+ },
+ function() {
+ node.elaborated
= false;
+
self.ongoingElaborations--;
+ }
+ );
}
else {
completeElaboration();
@@ -1939,11 +2008,16 @@
}
function completeElaboration( ) {
- var newExternalNodes =
self.externalLinksSuccessHandler( self, externalElaborationData, node,
forSecondOrderLinks );
- var newIntraOutNodes =
self.intraWikiOutSuccessHandler( self, intraOutElaborationData, node,
forSecondOrderLinks );
- var newIntraInNodes =
self.intraWikiInSuccessHandler( self, intraInElaborationData, node,
forSecondOrderLinks );
+ var newExternalNodes =
self.externalLinksSuccessHandler( self, externalElaborationData, node,
elaborationType );
+ var newIntraOutNodes =
self.intraWikiOutSuccessHandler( self, intraOutElaborationData, node,
elaborationType );
+ var newIntraInNodes =
self.intraWikiInSuccessHandler( self, intraInElaborationData, node,
elaborationType );
- if( !forSecondOrderLinks ) {
+ if( elaborationType ===
self.ELABORATION_TYPE_NORMAL ) {
+ self.log("redraw() - from
completeElaboration()");
+ self.redraw( true );
+ }
+
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS ) {
self.OngoingElaborationNodes =
self.OngoingElaborationNodes.concat(newExternalNodes);
self.OngoingElaborationNodes =
self.OngoingElaborationNodes.concat(newIntraOutNodes);
self.OngoingElaborationNodes =
self.OngoingElaborationNodes.concat(newIntraInNodes);
@@ -1953,24 +2027,26 @@
completionHandler( originNode );
}
- if( !forSecondOrderLinks ) {
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS ) {
if( self.showSecondOrderLinks )
{
- findSecondOrderLinks( );
+
self.ongoingElaborations--;
+ if(
self.ongoingElaborations == 0 ) {
+
findSecondOrderLinks( );
+ }
self.callHooks(
"NodeElaborationCompleteHook", [ originNode ] );
}
else {
-
self.visitNodeBatch(self.OngoingElaborationNodes.filter( function( node ) {
return node.apiURL !== null && node.apiURL !== undefined; } ) );
+
self.ongoingElaborations--;
+
self.log("self.ongoingElaborations = " + self.ongoingElaborations);
+
if(self.ongoingElaborations == 0) {
+
self.visitNodeBatch(self.OngoingElaborationNodes.filter( function( node ) {
return node.apiURL !== null && node.apiURL !== undefined; } ) );
+ }
}
}
}
}
function findSecondOrderLinks( ) {
- self.ongoingElaborations--;
- if( self.ongoingElaborations > 0 ) {
- return;
- }
-
// We must check all of the newly-added
(unvisited) nodes (self.OngoingElaborationNodes),
// as well as all "external wiki" nodes
currently in the graph (e.g. wiki nodes from another wiki).
// The other nodes in the graph from "this
wiki" we already know about, as their links to
@@ -1979,101 +2055,54 @@
return !node.visited;
} ).concat(
self.Nodes.filter( function( node ) {
- return node.type ==
self.WIKI_PAGE_TYPE && node.wikiTitle !== self.THIS_WIKI;
+ return node.type ===
self.WIKI_PAGE_TYPE && node.wikiTitle !== self.THIS_WIKI;
} )
);
var nodesChecked = 0, totalCheckCount =
nodesToCheck.length;
- if(totalCheckCount > 0) {
- // Set up the progress bar view for
calculating 2nd order links
- var secondOrderContent = '\
- <div id="secondOrderDiv">\
- <div id="textDiv">Finding 2nd
order links... 0%</div>\
- <div id="progressbarDiv"></div>\
- </div>';
-
- var loadingStyle = '\
- <style>\
- #textDiv {\
- text-align: center;\
- }\
- </style>';
-
- self.progressbarView = vex.open( {
- content: secondOrderContent,
- css: {
- "position": "absolute",
- "top" : "auto",
- "left" : "auto",
- "right" : "auto",
- "bottom" : "auto",
- "height" :
self.INITIAL_HEIGHT+"px",
- "width" :
self.INITIAL_WIDTH+"px"
- },
- contentCSS: {
- width: '300px'
- },
- appendLocation:
'#VIKI_'+self.ID+'_overlay',
- afterOpen: function(
$vexContent ) {
- $vexContent.append(
loadingStyle );
-
$('#progressbarDiv').progressbar({ max: nodesToCheck.length, value: 0 });
- },
- showCloseButton: false
- } );
-
- for( var i = 0; i <
nodesToCheck.length; i++ ) {
- var node = nodesToCheck[i];
- if( node.type ==
self.WIKI_PAGE_TYPE && node.searchable ) {
- self.elaborateWikiNode(
node, function( node ) {
- nodesChecked++;
-
$('#progressbarDiv').progressbar("value", nodesChecked);
-
$('#textDiv').text("Finding 2nd order links... "+ +(nodesChecked /
totalCheckCount * 100).toPrecision(4) + "%");
- if(nodesChecked
< totalCheckCount) {
- return;
- }
- vex.close(
self.progressbarView.data().vex.id );
-
- for(var i = 0;
i < self.TempLinks.length; i++) {
- var
link = self.TempLinks[ i ];
-
alreadyFound = self.findLink( link.source.identifier, link.target.identifier );
- if(
alreadyFound ) {
-
// If this link was found, check if it's a duplicate (source and targets are
same in both) or bidirectional (source and targets are reversed)
-
if(link.source.identifier == alreadyFound.target.identifier &&
link.source.identifier == alreadyFound.target.identifier)
-
alreadyFound.bidirectional = true;
-
continue;
- }
-
self.Links.push( link );
-
self.LinkMap[ link.source.identifier + "," + link.target.identifier ] = link;
-
self.LinkMap[ link.target.identifier + "," + link.source.identifier ] = link;
- }
- self.TempLinks
= [];
-
- for(var i = 0;
i < self.TempHiddenLinks.length; i++) {
- var
link = self.TempHiddenLinks[ i ];
- if(
!self.findHiddenLink( link.source, link.target ) ) {
-
self.HiddenLinks.push( link );
- }
- }
-
self.TempHiddenLinks = [];
-
self.log("redraw() - from findSecondOrderLinks");
- self.redraw(
true );
-
-
self.visitNodeBatch(self.OngoingElaborationNodes.filter( function( node ) {
return node.apiURL !== null && node.apiURL !== undefined; } ) );
- }, true );
- }
- else {
+ if(totalCheckCount <= 0) {
+ return;
+ }
+ self.showProgressOverlay("Finding 2nd order
links... 0%", nodesToCheck.length );
+
+ for( var i = 0; i < nodesToCheck.length; i++ ) {
+ var node = nodesToCheck[i];
+ if( node.type === self.WIKI_PAGE_TYPE
&& node.searchable ) {
+ self.elaborateWikiNode( node,
function( node ) {
nodesChecked++;
-
$('#textDiv').text("Finding 2nd order links..."+ +(nodesChecked /
totalCheckCount * 100).toPrecision(4) + "%");
-
$('#progressbarDiv').progressbar("value", nodesChecked);
- if( nodesChecked ==
totalCheckCount )
- vex.close(
self.progressbarView.data().vex.id );
- }
+
self.updateProgressOverlay( "Finding 2nd order links..."+ +(nodesChecked /
totalCheckCount * 100).toPrecision(4) + "%", nodesChecked);
+ if(nodesChecked <
totalCheckCount) {
+ return;
+ }
+
+
self.closeProgressOverlay( );
+
+
self.addTempLinksToGraph();
+
+ for(var i = 0; i <
self.TempHiddenLinks.length; i++) {
+ var link =
self.TempHiddenLinks[ i ];
+ if(
!self.findHiddenLink( link.source, link.target ) ) {
+
self.HiddenLinks.push( link );
+ }
+ }
+ self.TempHiddenLinks =
[];
+ self.log("redraw() -
from findSecondOrderLinks");
+ self.redraw( true );
+
+
self.visitNodeBatch(self.OngoingElaborationNodes.filter( function( node ) {
return node.apiURL !== null && node.apiURL !== undefined; } ) );
+ },
self.ELABORATION_TYPE_SECOND_ORDER_LINKS );
+ }
+ else {
+ nodesChecked++;
+ self.updateProgressOverlay(
"Finding 2nd order links..."+ +(nodesChecked / totalCheckCount *
100).toPrecision(4) + "%", nodesChecked);
+ if( nodesChecked ===
totalCheckCount )
+
self.closeProgressOverlay( );
}
}
}
};
- my.VikiJS.prototype.externalLinksSuccessHandler = function( context,
data, originNode, forSecondOrderLinks ) {
+ my.VikiJS.prototype.externalLinksSuccessHandler = function( context,
data, originNode, elaborationType ) {
if ( data.error ) {
context.showError( mw.message(
'viki-error-external-links', node.pageTitle )
@@ -2107,17 +2136,21 @@
var externalWikiNode =
context.findNode( "URL", thisURL );
if ( !externalWikiNode ) {
- if( forSecondOrderLinks
)
+ if( elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
continue;
externalWikiNode =
context.createWikiNodeFromExternalLink( thisURL, index );
context.callHooks(
"NewWikiNodeCreatedHook", [ externalWikiNode, originNode ] );
if (
externalWikiNode.unadded )
continue;
- else
-
context.addNode( externalWikiNode );
+ else {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+
context.TempNodes.push( externalWikiNode );
+ else
+
context.addNode( externalWikiNode );
+ }
}
- if(forSecondOrderLinks) {
+ if(elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS) {
link =
context.findLink( originNode.identifier, externalWikiNode.identifier );
if ( !link ) {
// If the link
doesn't exist, add it - hidden, if necessary.
@@ -2138,8 +2171,13 @@
}
}
link =
context.findLink( originNode.identifier, externalWikiNode.identifier );
- if ( !link )
- link =
context.addLink( originNode, externalWikiNode, hasHiddenCategory );
+ if ( !link ) {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+ link =
context.addTempLink( originNode, externalWikiNode );
+ else
+ link =
context.addLink( originNode, externalWikiNode, hasHiddenCeategory );
+ }
+
else {
link.bidirectional = true;
}
@@ -2148,17 +2186,21 @@
} else {
externalNode =
context.findNode( "URL", thisURL );
if ( !externalNode ) {
- if( forSecondOrderLinks
)
+ if( elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
continue;
externalNode =
context.createExternalNode( thisURL );
context.callHooks(
"NewExternalNodeCreatedHook", [ externalNode, originNode ] );
if (
externalNode.unadded )
continue;
- else
-
context.addNode( externalNode );
+ else {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+
context.TempNodes.push( externalNode );
+ else
+
context.addNode( externalNode );
+ }
}
- if(forSecondOrderLinks) {
+ if(elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS) {
link =
context.findLink( originNode.identifier, externalNode.identifier );
if ( !link ) {
link =
context.addSecondOrderLink( originNode, externalNode, externalNode.hidden );
@@ -2172,8 +2214,12 @@
}
}
link =
context.findLink( originNode.identifier, externalNode.identifier );
- if ( !link )
- link =
context.addLink( originNode, externalNode, hasHiddenCategory );
+ if ( !link ) {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+ link =
context.addTempLink( originNode, externalNode );
+ else
+ link =
context.addLink( originNode, externalNode, hasHiddenCategory );
+ }
else {
link.bidirectional = true;
}
@@ -2183,17 +2229,13 @@
newExternalNodes.push(
externalNode );
}
- if( !forSecondOrderLinks )
- context.callHooks( "ExternalNodeHook",
[ newExternalNodes.filter(function(node) { return node.type ==
self.EXTERNAL_PAGE_TYPE; } ) ] );
- }
- if( !forSecondOrderLinks ) {
- self.log("redraw() - from
externalLinksSuccessHandler");
- context.redraw( true );
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
+ context.callHooks( "ExternalNodeHook",
[ newExternalNodes.filter(function(node) { return node.type ===
self.EXTERNAL_PAGE_TYPE; } ) ] );
}
return newExternalNodes;
}
- my.VikiJS.prototype.intraWikiOutSuccessHandler = function(
context, data, originNode, forSecondOrderLinks ) {
+ my.VikiJS.prototype.intraWikiOutSuccessHandler = function(
context, data, originNode, elaborationType ) {
var thisContext = this;
if ( data.error ) {
@@ -2213,7 +2255,7 @@
for ( var i = 0; i < intraLinks.length; i++ ) {
intraNode = context.findNode(
"pageTitle", intraLinks[ i ].title );
if ( !intraNode || ( intraNode.apiURL
!== originNode.apiURL ) ) {
- if( forSecondOrderLinks )
+ if( elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
continue;
// add the node to the graph
immediately if it is within the wiki's content namespaces.
@@ -2223,14 +2265,18 @@
context.callHooks(
"NewWikiNodeCreatedHook", [ intraNode, originNode ] );
if ( intraNode.unadded )
continue;
- else
-
context.addNode( intraNode );
+ else {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+
context.TempNodes.push( intraNode );
+ else
+
context.addNode( intraNode );
+ }
} else
continue;
}
if ( intraNode ) {
- if(forSecondOrderLinks) {
+ if(elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS) {
var link =
context.findLink( originNode.identifier, intraNode.identifier );
if ( !link ) {
// If the link
doesn't exist, add it - hidden, if necessary.
@@ -2251,8 +2297,12 @@
}
var link =
context.findLink( originNode.identifier, intraNode.identifier );
if ( !link ) {
- link =
context.addLink( originNode, intraNode, hasHiddenCategory );
- } else {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+ link =
context.addTempLink( originNode, intraNode );
+ else
+ link =
context.addLink( originNode, intraNode, hasHiddenCategory );
+ }
+ else {
// if the found
link has this originNode as the SOURCE, this is an already known link OUT;
disregard.
// if the found
link has this originNode as the TARGET, this is a NEW link out; set as
bidirectional.
if (
!link.bidirectional && link.target.identifier === originNode.identifier )
@@ -2263,17 +2313,13 @@
newIntraOutNodes.push( intraNode );
}
- if( !forSecondOrderLinks )
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
context.callHooks( "IntraOutNodeHook",
[ newIntraOutNodes ] );
- }
- if( !forSecondOrderLinks ) {
- self.log("redraw() - from
intraWikiOutSuccessHandler");
- context.redraw( true );
}
return newIntraOutNodes;
}
- my.VikiJS.prototype.intraWikiInSuccessHandler = function(
context, data, originNode, forSecondOrderLinks ) {
+ my.VikiJS.prototype.intraWikiInSuccessHandler = function(
context, data, originNode, elaborationType ) {
if ( data.error ) {
context.showError( mw.message(
'viki-error-intrawiki-in', node.pageTitle )
@@ -2293,7 +2339,7 @@
for ( var i = 0; i < intraLinks.length; i++ ) {
intraNode = context.findNode(
"pageTitle", intraLinks[ i ].title );
if ( !intraNode || ( intraNode.apiURL
!== originNode.apiURL ) ) {
- if( forSecondOrderLinks )
+ if( elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
continue;
// add the node to the graph
immediately if it is within the wiki's content namespaces.
@@ -2303,14 +2349,18 @@
context.callHooks(
"NewWikiNodeCreatedHook", [ intraNode, originNode ] );
if ( intraNode.unadded )
continue;
- else
-
context.addNode( intraNode );
+ else {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+
context.TempNodes.push( intraNode );
+ else
+
context.addNode( intraNode );
+ }
} else
continue;
}
if ( intraNode ) {
- if(forSecondOrderLinks) {
+ if(elaborationType ===
self.ELABORATION_TYPE_SECOND_ORDER_LINKS) {
var link =
context.findLink( intraNode.identifier, originNode.identifier );
if ( !link )
// If the link
doesn't exist, add it - hidden, if necessary.
@@ -2330,8 +2380,12 @@
}
}
var link =
context.findLink( intraNode.identifier, originNode.identifier );
- if ( !link )
- link =
context.addLink( intraNode, originNode, hasHiddenCategory ); // opposite order
because these are pages coming IN
+ if ( !link ) {
+
if(elaborationType === self.ELABORATION_TYPE_INITIAL_POPULATION)
+ link =
context.addTempLink( intraNode, originNode ); // opposite order because these
are pages coming IN
+ else
+ link =
context.addLink( intraNode, originNode, hasHiddenCategory ); // opposite order
because these are pages coming IN
+ }
else {
// if the found
link has this originNode as the TARGET, this is an already known link IN;
disregard.
// if the found
link has this originNode as the SOURCE, this is a NEW link in; set as
bidirectional.
@@ -2344,17 +2398,100 @@
newIntraInNodes.push( intraNode );
}
- if( !forSecondOrderLinks )
+ if( elaborationType !==
self.ELABORATION_TYPE_SECOND_ORDER_LINKS )
context.callHooks( "IntraInNodeHook", [
newIntraInNodes ] );
- }
- if( !forSecondOrderLinks ) {
- self.log("redraw() - from
intraWikiInSuccessHandler");
- context.redraw( true );
}
return newIntraInNodes;
}
+ /**
+ * Show a progress bar overlay over the graph.
+ *
+ * @param {String} text text to show above the progress bar
+ * @param {Integer} maxValue max value of the progress bar
+ */
+ my.VikiJS.prototype.showProgressOverlay = function( text,
maxValue ) {
+ // Set up the progress bar view for calculating 2nd
order links
+ var secondOrderContent = '\
+ <div id="overlayDiv">\
+ <div id="textDiv">'+text+'</div>\
+ <div class="progressbarDiv"></div>\
+ </div>';
+
+ var loadingStyle = '\
+ <style>\
+ #textDiv {\
+ text-align: center;\
+ }\
+ </style>';
+
+ self.progressbarView = vex.open( {
+ content: secondOrderContent,
+ css: {
+ "position": "absolute",
+ "top" : "auto",
+ "left" : "auto",
+ "right" : "auto",
+ "bottom" : "auto",
+ "height" : self.INITIAL_HEIGHT+"px",
+ "width" : self.INITIAL_WIDTH+"px"
+ },
+ contentCSS: {
+ width: '300px'
+ },
+ appendLocation: '#VIKI_'+self.ID+'_overlay',
+ afterOpen: function( $vexContent ) {
+ $vexContent.append( loadingStyle );
+ $('.progressbarDiv').progressbar({ max:
maxValue, value: 0 });
+ },
+ showCloseButton: false
+ } );
+ }
+
+ /**
+ * Update the progress overlay.
+ *
+ * @param {String} text text to show above the progress bar
+ * @param {Integer} value current value of the progress bar
+ */
+ my.VikiJS.prototype.updateProgressOverlay = function( text,
value ) {
+ $('#textDiv').text(text);
+ $('.progressbarDiv').progressbar("value", value);
+ }
+
+ /**
+ * Close the progress overlay.
+ */
+ my.VikiJS.prototype.closeProgressOverlay = function( ) {
+ vex.close( self.progressbarView.data().vex.id );
+ self.progressbarView = null;
+ }
+
+ my.VikiJS.prototype.showWarningDialog = function( text,
yesCompletion, noCompletion ) {
+ vex.dialog.buttons.YES.text = 'Yes';
+ vex.dialog.buttons.NO.text = 'No';
+
+ vex.dialog.confirm({
+ css: {
+ "position": "absolute",
+ "top" : "auto",
+ "left" : "auto",
+ "right" : "auto",
+ "bottom" : "auto",
+ "height" : self.INITIAL_HEIGHT+"px",
+ "width" : self.INITIAL_WIDTH+"px"
+ },
+ appendLocation: '#VIKI_'+self.ID+'_overlay',
+ message: text,
+ callback: function(value) {
+ if( value )
+ if(yesCompletion)
yesCompletion();
+ else
+ if(noCompletion) noCompletion();
+ }
+ });
+ }
/**
* Hide this node and all associated links from the graph.
@@ -2576,15 +2713,7 @@
self.HiddenNodes = [];
// 2. Add all hidden links back into main Links array.
Also add all hidden links back into the LinkMap.
- // Then destroy hidden links array.
- for ( i = 0; i < self.HiddenLinks.length; i++ ) {
- var link = self.HiddenLinks[ i ];
- self.Links.push( link );
- self.LinkMap[ link.source.identifier + "," +
link.target.identifier ] = link;
- self.LinkMap[ link.target.identifier + "," +
link.source.identifier ] = link;
- }
-
- self.HiddenLinks = [];
+ self.addHiddenLinksToGraph();
self.Nodes.forEach( function( node ) {
node.hidingIncoming = false;
@@ -2610,7 +2739,7 @@
* @return {hasHiddenCategory} true if the node has a hidden
category, false if not
*/
my.VikiJS.prototype.nodeHasHiddenCategory = function( node ) {
- if( node.type == self.EXTERNAL_PAGE_TYPE )
+ if( node.type === self.EXTERNAL_PAGE_TYPE )
return false;
if( !node.categories )
return false;
diff --git a/VIKI.php b/VIKI.php
index 4058225..ffa8758 100644
--- a/VIKI.php
+++ b/VIKI.php
@@ -31,7 +31,7 @@
* refreshLinks.php after setting this flag.
*/
-define( 'VIKIJS_VERSION', '1.2.1' );
+define( 'VIKIJS_VERSION', '1.3' );
if ( !defined( 'MEDIAWIKI' ) ) {
die( '<b>Error:</b> This file is part of a MediaWiki extension and
cannot be run standalone.' );
@@ -121,6 +121,8 @@
$delimiter = isset( $paramDictionary['delimiter'] ) ?
$paramDictionary['delimiter'] : ',';
$pageTitles = isset( $paramDictionary['pageTitles'] ) ? explode(
$delimiter,
$paramDictionary['pageTitles'] ) : array(
$parser->getTitle()->getText() );
+ $categories = isset( $paramDictionary['categories'] ) ? explode(
$delimiter,
+ $paramDictionary['categories'] ) : array();
if( isset( $paramDictionary['secondOrderLinks'] ) )
$showSecondOrderLinks = $paramDictionary['secondOrderLinks'] ==
'true' ? true : false;
else if( $wgVIKI_Second_Order_Links !== null )
@@ -128,6 +130,20 @@
else
$showSecondOrderLinks = false;
+ $pageTitles = array_map('trim', $pageTitles);
+ foreach($categories as $categoryName) {
+ $categoryObject = Category::newFromName($categoryName);
+ $categoryMembers = $categoryObject->getMembers();
+ foreach($categoryMembers->res as $row) {
+ $titleObject = Title::newFromID( $row->page_id );
+ if( $titleObject ) {
+ $titleText = $titleObject->getPrefixedText();
+ if( !in_array( $titleText, $pageTitles ) )
+ $pageTitles[] = $titleText;
+ }
+ }
+ }
+
$vikiJS = new VikiJS;
$output = $vikiJS->display( $parser, $pageTitles, $width, $height,
$showSecondOrderLinks );
$parser->disableCache();
--
To view, visit https://gerrit.wikimedia.org/r/244600
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Iaa0fb28e8330bc2c0fa99a673987da5f98b37535
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/VIKI
Gerrit-Branch: master
Gerrit-Owner: Jason.ji <[email protected]>
Gerrit-Reviewer: Jason.ji <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits