Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2893061
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
19 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/webroot/rsrc/js/application/core/ShapedRequest.js b/webroot/rsrc/js/application/core/ShapedRequest.js
index dd03b30def..0f0e0d68d1 100644
--- a/webroot/rsrc/js/application/core/ShapedRequest.js
+++ b/webroot/rsrc/js/application/core/ShapedRequest.js
@@ -1,93 +1,94 @@
/**
* @requires javelin-install
* javelin-util
* javelin-request
* @provides phabricator-shaped-request
* @javelin
*/
/**
* Send requests with rate limiting and retries, in response to some application
* trigger. This is used to implement comment previews in Differential and
* Maniphest.
*/
JX.install('PhabricatorShapedRequest', {
construct : function(uri, callback, data_callback) {
this._uri = uri;
this._callback = callback;
this._dataCallback = data_callback;
},
members : {
_callback : null,
_dataCallback : null,
_request : null,
_min : null,
_defer : null,
_last : null,
start : function() {
this.trigger();
},
trigger : function() {
if (this._request) {
// Waiting on a request, rate-limit.
return;
}
if (this._min && (new Date().getTime() < this._min)) {
// Just got a request back, rate-limit.
return;
}
- this._defer && this._defer.stop();
-
+ clearTimeout(this._defer);
var data = this._dataCallback();
if (this.shouldSendRequest(this._last, data)) {
this._last = data;
var request = new JX.Request(this._uri, JX.bind(this, function(r) {
this._callback(r);
this._min = new Date().getTime() + this.getRateLimit();
- this._defer && this._defer.stop();
- this._defer = JX.defer(
+ clearTimeout(this._defer);
+ this._defer = setTimeout(
JX.bind(this, this.trigger),
- this.getRateLimit());
+ this.getRateLimit()
+ );
}));
request.listen('finally', JX.bind(this, function() {
this._request = null;
}));
request.setData(data);
request.setTimeout(this.getRequestTimeout());
request.send();
} else {
- this._defer = JX.defer(
+ this._defer = setTimeout(
JX.bind(this, this.trigger),
- this.getFrequency());
+ this.getFrequency()
+ );
}
},
shouldSendRequest : function(last, data) {
if (last === null) {
return true;
}
for (var k in last) {
if (data[k] !== last[k]) {
return true;
}
}
return false;
}
},
properties : {
rateLimit : 500,
frequency : 1000,
requestTimeout : 20000
}
});
diff --git a/webroot/rsrc/js/application/core/behavior-drag-and-drop.js b/webroot/rsrc/js/application/core/behavior-drag-and-drop.js
index 623fa92cbc..280a62292a 100644
--- a/webroot/rsrc/js/application/core/behavior-drag-and-drop.js
+++ b/webroot/rsrc/js/application/core/behavior-drag-and-drop.js
@@ -1,92 +1,92 @@
/**
* @provides javelin-behavior-aphront-drag-and-drop
* @requires javelin-behavior
* javelin-dom
* javelin-util
* phabricator-drag-and-drop-file-upload
*/
JX.behavior('aphront-drag-and-drop', function(config) {
// The control renders hidden by default; if we don't have support for
// drag-and-drop just leave it hidden.
if (!JX.PhabricatorDragAndDropFileUpload.isSupported()) {
return;
}
// Show the control, since we have browser support.
JX.$(config.control).style.display = '';
var files = config.value || {};
var pending = 0;
var list = JX.$(config.list);
var drop = new JX.PhabricatorDragAndDropFileUpload(JX.$(config.target))
.setActivatedClass(config.activatedClass)
.setURI(config.uri);
drop.listen('willUpload', function(f) {
pending++;
redraw();
});
drop.listen('didUpload', function(f) {
files[f.phid] = f;
// This redraws "Upload complete!"
pending--;
redraw(true);
// This redraws the instructions.
- JX.defer(redraw, 1000);
+ setTimeout(redraw, 1000);
});
drop.start();
redraw();
JX.DOM.listen(
list,
'click',
'aphront-attached-file-view-remove',
function(e) {
e.kill();
delete files[e.getTarget().getAttribute('ref')];
redraw();
});
function redraw(completed) {
var items = [];
for (var k in files) {
var file = files[k];
items.push(JX.$N('div', {}, JX.$H(file.html)));
items.push(JX.$N(
'input',
{
type: "hidden",
name: config.name + "[" + file.phid + "]",
value: file.phid
}));
}
var status;
if (!pending) {
if (completed) {
status = JX.$H('<strong>Upload complete!</strong>');
} else {
arrow = String.fromCharCode(0x21EA);
status = JX.$H(
arrow + ' <strong>Drag and Drop</strong> files here to upload them.');
}
} else {
status = JX.$H(
'Uploading <strong>' + parseInt(pending, 10) + '<strong> files...');
}
status = JX.$N('div', {className: 'drag-and-drop-instructions'}, status);
items.push(status);
JX.DOM.setContent(list, items);
}
});
diff --git a/webroot/rsrc/js/application/core/behavior-object-selector.js b/webroot/rsrc/js/application/core/behavior-object-selector.js
index 034fa579b1..9864a329e5 100644
--- a/webroot/rsrc/js/application/core/behavior-object-selector.js
+++ b/webroot/rsrc/js/application/core/behavior-object-selector.js
@@ -1,185 +1,183 @@
/**
* @provides javelin-behavior-phabricator-object-selector
* @requires javelin-behavior
* javelin-dom
* javelin-request
* javelin-util
* javelin-stratcom
*/
JX.behavior('phabricator-object-selector', function(config) {
var n = 0;
var phids = {};
var handles = config.handles;
for (var k in handles) {
phids[k] = true;
}
var attach_list = {};
var query_timer = null;
var query_delay = 50;
var phid_input = JX.DOM.find(
JX.$(config.form),
'input',
'aphront-dialog-application-input');
var last_value = JX.$(config.query).value;
function onreceive(seq, r) {
if (seq != n) {
return;
}
var display = [];
attach_list = {};
for (var k in r) {
handles[r[k].phid] = r[k];
display.push(renderHandle(r[k], true));
}
if (!display.length) {
display = renderNote('No results.');
}
JX.DOM.setContent(JX.$(config.results), display);
}
function redrawAttached() {
var display = [];
for (var k in phids) {
display.push(renderHandle(handles[k], false));
}
if (!display.length) {
display = renderNote('Nothing attached.');
}
JX.DOM.setContent(JX.$(config.current), display);
phid_input.value = JX.keys(phids).join(';');
}
function renderHandle(h, attach) {
var link = JX.$N(
'a',
{href : h.uri, target : '_blank'},
h.name);
var td = JX.$N('td');
var table = JX.$N(
'table',
{className: 'phabricator-object-selector-handle'},
JX.$N(
'tbody',
{},
[JX.$N('th', {}, link), td]));
var btn = JX.$N(
'a',
{className: 'button small grey'},
attach ? 'Select' : 'Remove');
JX.Stratcom.addSigil(btn, 'object-attach-button');
JX.Stratcom.addData(btn, {handle : h, table : table});
if (attach) {
attach_list[h.phid] = btn;
if (h.phid in phids) {
JX.DOM.alterClass(btn, 'disabled', true);
btn.disabled = true;
}
}
JX.DOM.setContent(td, btn);
return table;
}
function renderNote(note) {
return JX.$N('div', {className : 'object-selector-nothing'}, note);
}
function sendQuery() {
query_timer = null;
JX.DOM.setContent(JX.$(config.results), renderNote('Loading...'))
new JX.Request(config.uri, JX.bind(null, onreceive, ++n))
.setData({
filter: JX.$(config.filter).value,
query: JX.$(config.query).value
})
.send();
}
JX.DOM.listen(
JX.$(config.results),
'click',
'object-attach-button',
function(e) {
e.kill();
var button = e.getNode('object-attach-button');
if (button.disabled) {
return;
}
var data = e.getNodeData('object-attach-button');
phids[data.handle.phid] = true;
JX.DOM.alterClass(button, 'disabled', true);
button.disabled = true;
redrawAttached();
});
JX.DOM.listen(
JX.$(config.current),
'click',
'object-attach-button',
function(e) {
e.kill();
var button = e.getNode('object-attach-button');
if (button.disabled) {
return;
}
var data = e.getNodeData('object-attach-button');
delete phids[data.handle.phid];
if (attach_list[data.handle.phid]) {
JX.DOM.alterClass(attach_list[data.handle.phid], 'disabled', false);
attach_list[data.handle.phid].disabled = false;
}
redrawAttached();
});
JX.DOM.listen(
JX.$(config.filter),
'change',
null,
function(e) {
e.kill();
sendQuery();
});
JX.DOM.listen(
JX.$(config.query),
['change', 'keydown', 'keyup', 'keypress'],
null,
function(e) {
var cur_value = JX.$(config.query).value;
if (last_value == cur_value) {
return;
}
last_value = cur_value;
- if (query_timer) {
- query_timer.stop();
- }
- query_timer = JX.defer(sendQuery, query_delay);
+ clearTimeout(query_timer);
+ query_timer = setTimeout(sendQuery, query_delay);
});
sendQuery();
redrawAttached();
});
diff --git a/webroot/rsrc/js/application/core/behavior-watch-anchor.js b/webroot/rsrc/js/application/core/behavior-watch-anchor.js
index 0fc429b04a..8d8c0e5ca1 100644
--- a/webroot/rsrc/js/application/core/behavior-watch-anchor.js
+++ b/webroot/rsrc/js/application/core/behavior-watch-anchor.js
@@ -1,34 +1,33 @@
/**
* @provides javelin-behavior-phabricator-watch-anchor
* @requires javelin-behavior
* javelin-stratcom
* javelin-util
* javelin-dom
*/
JX.behavior('phabricator-watch-anchor', function() {
var highlighted;
function highlight() {
highlighted && JX.DOM.alterClass(highlighted, 'anchor-target', false);
try {
highlighted = JX.$('anchor-' + window.location.hash.replace('#', ''));
JX.DOM.alterClass(highlighted, 'anchor-target', true);
} catch (ex) {
if (ex === JX.$.NotFound) {
highlighted = null;
} else {
throw ex;
}
}
}
- JX.Stratcom.listen(
- 'hashchange',
- null,
- // Defer invocation so other listeners can update the document.
- function() { JX.defer(highlight); });
-
- JX.defer(highlight);
+ // Defer invocation so other listeners can update the document.
+ var fn = function() {
+ setTimeout(highlight, 0);
+ };
+ JX.Stratcom.listen('hashchange', null, fn);
+ fn();
});
diff --git a/webroot/rsrc/js/application/countdown/timer.js b/webroot/rsrc/js/application/countdown/timer.js
index ef944e6cd0..c7de7b7582 100644
--- a/webroot/rsrc/js/application/countdown/timer.js
+++ b/webroot/rsrc/js/application/countdown/timer.js
@@ -1,48 +1,48 @@
/**
* @provides javelin-behavior-countdown-timer
* @requires javelin-behavior
* javelin-dom
* javelin-util
*/
JX.behavior('countdown-timer', function(config) {
calculateTimeLeft();
function calculateTimeLeft() {
var days = 0;
var hours = 0;
var minutes = 0;
var seconds = 0;
var current_timestamp = Math.round(new Date() / 1000);
var delta = config.timestamp - current_timestamp;
if (delta <= 0) {
JX.DOM.setContent(JX.$('phabricator-timer-days'), days);
JX.DOM.setContent(JX.$('phabricator-timer-hours'), hours);
JX.DOM.setContent(JX.$('phabricator-timer-minutes'), minutes);
JX.DOM.setContent(JX.$('phabricator-timer-seconds'), seconds);
return;
}
days = Math.floor(delta/86400);
delta -= days * 86400;
hours = Math.floor(delta/3600);
delta -= hours * 3600;
minutes = Math.floor(delta / 60);
delta -= minutes * 60;
seconds = delta;
JX.DOM.setContent(JX.$('phabricator-timer-days'), days);
JX.DOM.setContent(JX.$('phabricator-timer-hours'), hours);
JX.DOM.setContent(JX.$('phabricator-timer-minutes'), minutes);
JX.DOM.setContent(JX.$('phabricator-timer-seconds'), seconds);
- JX.defer(calculateTimeLeft, 1000);
+ setTimeout(calculateTimeLeft, 1000);
}
});
diff --git a/webroot/rsrc/js/application/diffusion/behavior-jump-to.js b/webroot/rsrc/js/application/diffusion/behavior-jump-to.js
index 46604a4d66..6c51dc814a 100644
--- a/webroot/rsrc/js/application/diffusion/behavior-jump-to.js
+++ b/webroot/rsrc/js/application/diffusion/behavior-jump-to.js
@@ -1,17 +1,15 @@
/**
* @provides javelin-behavior-diffusion-jump-to
* @requires javelin-behavior
* javelin-util
* javelin-vector
* javelin-dom
*/
JX.behavior('diffusion-jump-to', function(config) {
- JX.defer(
- function() {
- window.scrollTo(0, JX.$V(JX.$(config.target)).y - 100);
- });
+ setTimeout(function() {
+ window.scrollTo(0, JX.$V(JX.$(config.target)).y - 100);
+ }, 0);
});
-
diff --git a/webroot/rsrc/js/application/herald/PathTypeahead.js b/webroot/rsrc/js/application/herald/PathTypeahead.js
index 7ef3a9b094..988d728ced 100644
--- a/webroot/rsrc/js/application/herald/PathTypeahead.js
+++ b/webroot/rsrc/js/application/herald/PathTypeahead.js
@@ -1,206 +1,205 @@
/**
* @requires javelin-install
* javelin-typeahead
* javelin-dom
* javelin-request
* javelin-typeahead-ondemand-source
* javelin-util
* @provides path-typeahead
* @javelin
*/
JX.install('PathTypeahead', {
construct : function(config) {
this._repositorySelect = config.repo_select;
this._hardpoint = config.hardpoint;
this._input = config.path_input;
this._completeURI = config.completeURI;
this._validateURI = config.validateURI;
this._errorDisplay = config.error_display;
/*
* Default values to preload the typeahead with, for extremely common
* cases.
*/
this._textInputValues = config.repositoryDefaultPaths;
this._initializeDatasource();
this._initializeTypeahead(this._input);
},
members : {
/*
* DOM <select> elem for choosing the repository of a path.
*/
_repositorySelect : null,
/*
* DOM parent div "hardpoint" to be passed to the JX.Typeahead.
*/
_hardpoint : null,
/*
* DOM element to display errors.
*/
_errorDisplay : null,
/*
* URI to query for typeahead results, to be passed to the
* TypeaheadOnDemandSource.
*/
_completeURI : null,
/*
* Underlying JX.TypeaheadOnDemandSource instance
*/
_datasource : null,
/*
* Underlying JX.Typeahead instance
*/
_typeahead : null,
/*
* Underlying input
*/
_input : null,
/*
* Whenever the user changes the typeahead value, we track the change
* here, keyed by the selected repository ID. That way, we can restore
* typed values if they change the repository choice and then change back.
*/
_textInputValues : null,
/*
* Configurable endpoint for server-side path validation
*/
_validateURI : null,
/*
* Keep the validation AJAX request so we don't send several.
*/
_validationInflight : null,
/*
* Installs path-specific behaviors and then starts the underlying
* typeahead.
*/
start : function() {
if (this._typeahead.getValue()) {
this._textInputValues[this._repositorySelect.value] =
this._typeahead.getValue();
}
this._typeahead.listen(
'change',
JX.bind(this, function(value) {
this._textInputValues[this._repositorySelect.value] = value;
this._validate();
}));
this._typeahead.listen(
'choose',
JX.bind(this, function() {
- JX.defer(
- JX.bind(this._typeahead, this._typeahead.refresh));
+ setTimeout(JX.bind(this._typeahead, this._typeahead.refresh), 0);
}));
var repo_set_input = JX.bind(this, this._onrepochange);
this._typeahead.listen('start', repo_set_input);
JX.DOM.listen(
this._repositorySelect,
'change',
null,
repo_set_input);
this._typeahead.start();
this._validate();
},
_onrepochange : function() {
this._setPathInputBasedOnRepository(
this._typeahead,
this._textInputValues);
this._datasource.setAuxiliaryData(
{repositoryPHID : this._repositorySelect.value}
);
},
_setPathInputBasedOnRepository : function(typeahead, lookup) {
if (lookup[this._repositorySelect.value]) {
typeahead.setValue(lookup[this._repositorySelect.value]);
} else {
typeahead.setValue('/');
}
},
_initializeDatasource : function() {
this._datasource = new JX.TypeaheadOnDemandSource(this._completeURI);
this._datasource.setNormalizer(this._datasourceNormalizer);
this._datasource.setQueryDelay(40);
},
/*
* Construct and initialize the Typeahead.
* Must be called after initializing the datasource.
*/
_initializeTypeahead : function(path_input) {
this._typeahead = new JX.Typeahead(this._hardpoint, path_input);
this._datasource.setMaximumResultCount(15);
this._typeahead.setDatasource(this._datasource);
},
_datasourceNormalizer : function(str) {
return ('' + str).replace(/[\/]+/g, '\/');
},
_validate : function() {
var input = this._input;
var repo_id = this._repositorySelect.value;
var input_value = input.value;
var error_display = this._errorDisplay;
if (!input_value.length) {
input.value = '/';
input_value = '/';
}
if (this._validationInflight) {
this._validationInflight.abort();
this._validationInflight = null;
}
var validation_request = new JX.Request(
this._validateURI,
function(payload) {
// Don't change validation display state if the input has been
// changed since we started validation
if (input.value === input_value) {
if (payload.valid) {
JX.DOM.alterClass(error_display, 'invalid', false);
JX.DOM.alterClass(error_display, 'valid', true);
} else {
JX.DOM.alterClass(error_display, 'invalid', true);
JX.DOM.alterClass(error_display, 'valid', false);
}
JX.DOM.setContent(error_display, payload.message);
}
});
validation_request.listen('finally', function() {
JX.DOM.alterClass(error_display, 'validating', false);
this._validationInflight = null;
});
validation_request.setData(
{
repositoryPHID : repo_id,
path : input_value
});
this._validationInflight = validation_request;
validation_request.setTimeout(750);
validation_request.send();
}
}
});
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:47 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127120
Default Alt Text
(19 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment