diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 065dcaf26a..5ed5040c3d 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -969,7 +969,7 @@ celerity_register_resource_map(array(
),
'javelin-behavior-countdown-timer' =>
array(
- 'uri' => '/res/5ee9cb13/rsrc/js/application/countdown/timer.js',
+ 'uri' => '/res/7468acb7/rsrc/js/application/countdown/timer.js',
'type' => 'js',
'requires' =>
array(
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index d41d493f13..889838b867 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -928,6 +928,7 @@ phutil_register_library_map(array(
'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php',
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php',
+ 'PhabricatorRemarkupRuleCountdown' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleCountdown.php',
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleDifferential.php',
'PhabricatorRemarkupRuleDifferentialHandle' => 'infrastructure/markup/rule/handle/PhabricatorRemarkupRuleDifferentialHandle.php',
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleDiffusion.php',
@@ -2015,6 +2016,7 @@ phutil_register_library_map(array(
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
+ 'PhabricatorRemarkupRuleCountdown' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleDifferentialHandle' => 'PhabricatorRemarkupRuleObjectHandle',
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
diff --git a/src/applications/countdown/controller/PhabricatorCountdownViewController.php b/src/applications/countdown/controller/PhabricatorCountdownViewController.php
index 74179be04b..90cf629d15 100644
--- a/src/applications/countdown/controller/PhabricatorCountdownViewController.php
+++ b/src/applications/countdown/controller/PhabricatorCountdownViewController.php
@@ -47,8 +47,9 @@ final class PhabricatorCountdownViewController
),
$chrome_visible ? 'Disable Chrome' : 'Enable Chrome');
+ $container = celerity_generate_unique_node_id();
$content =
- '
';
Javelin::initBehavior('countdown-timer', array(
- 'timestamp' => $timer->getDatepoint()
+ 'timestamp' => $timer->getDatepoint(),
+ 'container' => $container,
));
$panel = $content;
diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php
index 0073e565b3..f9e11d520d 100644
--- a/src/infrastructure/markup/PhabricatorMarkupEngine.php
+++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php
@@ -411,6 +411,8 @@ final class PhabricatorMarkupEngine {
$rules[] = new PhabricatorRemarkupRuleManiphest();
$rules[] = new PhabricatorRemarkupRulePaste();
+ $rules[] = new PhabricatorRemarkupRuleCountdown();
+
$rules[] = new PonderRuleQuestion();
if ($options['macros']) {
diff --git a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleCountdown.php b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleCountdown.php
new file mode 100644
index 0000000000..2d67ba270c
--- /dev/null
+++ b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleCountdown.php
@@ -0,0 +1,84 @@
+load($matches[1]);
+ if (!$countdown) {
+ return $matches[0];
+ }
+ $id = celerity_generate_unique_node_id();
+
+ $engine = $this->getEngine();
+ $token = $engine->storeText('');
+
+ $metadata_key = self::KEY_RULE_COUNTDOWN;
+ $metadata = $engine->getTextMetadata($metadata_key, array());
+ $metadata[$id] = array($countdown->getDatepoint(), $token);
+ $engine->setTextMetadata($metadata_key, $metadata);
+
+ return $token;
+ }
+
+ public function didMarkupText() {
+ $engine = $this->getEngine();
+
+ $metadata_key = self::KEY_RULE_COUNTDOWN;
+ $metadata = $engine->getTextMetadata($metadata_key, array());
+
+ require_celerity_resource('javelin-behavior-countdown-timer');
+
+ foreach ($metadata as $id => $info) {
+ list($time, $token) = $info;
+ $count = phutil_render_tag(
+ 'span',
+ array(
+ 'id' => $id,
+ ),
+ javelin_render_tag('span',
+ array('sigil' => 'phabricator-timer-days'), '').'d'.
+ javelin_render_tag('span',
+ array('sigil' => 'phabricator-timer-hours'), '').'h'.
+ javelin_render_tag('span',
+ array('sigil' => 'phabricator-timer-minutes'), '').'m'.
+ javelin_render_tag('span',
+ array('sigil' => 'phabricator-timer-seconds'), '').'s');
+ Javelin::initBehavior('countdown-timer', array(
+ 'timestamp' => $time,
+ 'container' => $id,
+ ));
+ $engine->overwriteStoredText($token, $count);
+ }
+
+ $engine->setTextMetadata($metadata_key, array());
+ }
+
+}
diff --git a/webroot/rsrc/js/application/countdown/timer.js b/webroot/rsrc/js/application/countdown/timer.js
index c7de7b7582..1b404b4609 100644
--- a/webroot/rsrc/js/application/countdown/timer.js
+++ b/webroot/rsrc/js/application/countdown/timer.js
@@ -7,8 +7,14 @@
JX.behavior('countdown-timer', function(config) {
+ var container = JX.$(config.container);
calculateTimeLeft();
+ function setComponent(which, content) {
+ var component = JX.DOM.find(container, '*', 'phabricator-timer-' + which);
+ JX.DOM.setContent(component, content);
+ }
+
function calculateTimeLeft() {
var days = 0;
var hours = 0;
@@ -18,31 +24,25 @@ JX.behavior('countdown-timer', function(config) {
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;
+ if (delta > 0) {
+ 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;
+
+ setTimeout(calculateTimeLeft, 1000);
}
- 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);
-
- setTimeout(calculateTimeLeft, 1000);
+ setComponent('days', days);
+ setComponent('hours', hours);
+ setComponent('minutes', minutes);
+ setComponent('seconds', seconds);
}
});