]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Merge pull request #830 from ArthurHoaro/theme/timezone
authorArthurHoaro <arthur@hoa.ro>
Tue, 25 Apr 2017 17:09:13 +0000 (19:09 +0200)
committerGitHub <noreply@github.com>
Tue, 25 Apr 2017 17:09:13 +0000 (19:09 +0200)
Change timezone data structure send to the templates

12 files changed:
application/PageBuilder.php
application/TimeZone.php
index.php
tests/TimeZoneTest.php
tpl/default/configure.html
tpl/default/install.html
tpl/default/js/shaarli.js
tpl/vintage/configure.html
tpl/vintage/css/shaarli.css
tpl/vintage/install.html
tpl/vintage/js/shaarli.js [new file with mode: 0644]
tpl/vintage/page.footer.html

index b133dee83644794f7617726a79e1d087f373f825..8e39455bffe443b975be7d376628e66382e7b8bc 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Shaarli\Config\ConfigManager;
+
 /**
  * This class is in charge of building the final page.
  * (This is basically a wrapper around RainTPL which pre-fills some fields.)
index 36a8fb122ada91a1832f25944895f8aeca599288..c1869ef87e1d0b96b105c792d8dc902c15ca5246 100644 (file)
@@ -1,23 +1,42 @@
 <?php
 /**
- * Generates the timezone selection form and JavaScript.
+ * Generates a list of available timezone continents and cities.
  *
- * Note: 'UTC/UTC' is mapped to 'UTC' to form a valid option
+ * Two distinct array based on available timezones
+ * and the one selected in the settings:
+ *   - (0) continents:
+ *     + list of available continents
+ *     + special key 'selected' containing the value of the selected timezone's continent
+ *   - (1) cities:
+ *     + list of available cities associated with their continent
+ *     + special key 'selected' containing the value of the selected timezone's city (without the continent)
  *
- * Example: preselect Europe/Paris
- *  list($htmlform, $js) = generateTimeZoneForm('Europe/Paris');
+ * Example:
+ *   [
+ *     [
+ *       'America',
+ *       'Europe',
+ *       'selected' => 'Europe',
+ *     ],
+ *     [
+ *       ['continent' => 'America', 'city' => 'Toronto'],
+ *       ['continent' => 'Europe', 'city' => 'Paris'],
+ *       'selected' => 'Paris',
+ *     ],
+ *   ];
  *
+ * Notes:
+ *   - 'UTC/UTC' is mapped to 'UTC' to form a valid option
+ *   - a few timezone cities includes the country/state, such as Argentina/Buenos_Aires
+ *   - these arrays are designed to build timezone selects in template files with any HTML structure
+ *
+ * @param array  $installedTimeZones  List of installed timezones as string
  * @param string $preselectedTimezone preselected timezone (optional)
  *
- * @return array containing the generated HTML form and Javascript code
+ * @return array[] continents and cities
  **/
-function generateTimeZoneForm($preselectedTimezone='')
+function generateTimeZoneData($installedTimeZones, $preselectedTimezone = '')
 {
-    // Select the server timezone
-    if ($preselectedTimezone == '') {
-        $preselectedTimezone = date_default_timezone_get();
-    }
-
     if ($preselectedTimezone == 'UTC') {
         $pcity = $pcontinent = 'UTC';
     } else {
@@ -27,62 +46,30 @@ function generateTimeZoneForm($preselectedTimezone='')
         $pcity = substr($preselectedTimezone, $spos+1);
     }
 
-    // The list is in the form 'Europe/Paris', 'America/Argentina/Buenos_Aires'
-    // We split the list in continents/cities.
-    $continents = array();
-    $cities = array();
-
-    // TODO: use a template to generate the HTML/Javascript form
-
-    foreach (timezone_identifiers_list() as $tz) {
+    $continents = [];
+    $cities = [];
+    foreach ($installedTimeZones as $tz) {
         if ($tz == 'UTC') {
             $tz = 'UTC/UTC';
         }
         $spos = strpos($tz, '/');
 
-        if ($spos !== false) {
-            $continent = substr($tz, 0, $spos);
-            $city = substr($tz, $spos+1);
-            $continents[$continent] = 1;
-
-            if (!isset($cities[$continent])) {
-                $cities[$continent] = '';
-            }
-            $cities[$continent] .= '<option value="'.$city.'"';
-            if ($pcity == $city) {
-                $cities[$continent] .= ' selected="selected"';
-            }
-            $cities[$continent] .= '>'.$city.'</option>';
+        // Ignore invalid timezones
+        if ($spos === false) {
+            continue;
         }
-    }
-
-    $continentsHtml = '';
-    $continents = array_keys($continents);
 
-    foreach ($continents as $continent) {
-        $continentsHtml .= '<option  value="'.$continent.'"';
-        if ($pcontinent == $continent) {
-            $continentsHtml .= ' selected="selected"';
-        }
-        $continentsHtml .= '>'.$continent.'</option>';
+        $continent = substr($tz, 0, $spos);
+        $city = substr($tz, $spos+1);
+        $cities[] = ['continent' => $continent, 'city' => $city];
+        $continents[$continent] = true;
     }
 
-    // Timezone selection form
-    $timezoneForm = 'Continent:';
-    $timezoneForm .= '<select name="continent" id="continent" onChange="onChangecontinent();">';
-    $timezoneForm .= $continentsHtml.'</select>';
-    $timezoneForm .= '&nbsp;&nbsp;&nbsp;&nbsp;City:';
-    $timezoneForm .= '<select name="city" id="city">'.$cities[$pcontinent].'</select><br />';
-
-    // Javascript handler - updates the city list when the user selects a continent
-    $timezoneJs = '<script>';
-    $timezoneJs .= 'function onChangecontinent() {';
-    $timezoneJs .= 'document.getElementById("city").innerHTML =';
-    $timezoneJs .= ' citiescontinent[document.getElementById("continent").value]; }';
-    $timezoneJs .= 'var citiescontinent = '.json_encode($cities).';';
-    $timezoneJs .= '</script>';
+    $continents = array_keys($continents);
+    $continents['selected'] = $pcontinent;
+    $cities['selected'] = $pcity;
 
-    return array($timezoneForm, $timezoneJs);
+    return [$continents, $cities];
 }
 
 /**
index 1e255583823a69626d469750b13640dee268e7f5..e392e501aee16891e6b7c24895b6e51d0130c60f 100644 (file)
--- a/index.php
+++ b/index.php
@@ -1146,9 +1146,12 @@ function renderPage($conf, $pluginManager, $LINKSDB)
             $PAGE->assign('theme', $conf->get('resource.theme'));
             $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
             $PAGE->assign('redirector', $conf->get('redirector.url'));
-            list($timezone_form, $timezone_js) = generateTimeZoneForm($conf->get('general.timezone'));
-            $PAGE->assign('timezone_form', $timezone_form);
-            $PAGE->assign('timezone_js',$timezone_js);
+            list($continents, $cities) = generateTimeZoneData(
+                timezone_identifiers_list(),
+                $conf->get('general.timezone')
+            );
+            $PAGE->assign('continents', $continents);
+            $PAGE->assign('cities', $cities);
             $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false));
             $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false));
             $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
@@ -1969,16 +1972,10 @@ function install($conf)
         exit;
     }
 
-    // Display config form:
-    list($timezone_form, $timezone_js) = generateTimeZoneForm();
-    $timezone_html = '';
-    if ($timezone_form != '') {
-        $timezone_html = '<tr><td><b>Timezone:</b></td><td>'.$timezone_form.'</td></tr>';
-    }
-
     $PAGE = new PageBuilder($conf);
-    $PAGE->assign('timezone_html',$timezone_html);
-    $PAGE->assign('timezone_js',$timezone_js);
+    list($continents, $cities) = generateTimeZoneData(timezone_identifiers_list(), date_default_timezone_get());
+    $PAGE->assign('continents', $continents);
+    $PAGE->assign('cities', $cities);
     $PAGE->renderPage('install');
     exit;
 }
index 2976d11612765dde427242073320c4d7f32bdb97..127fdc192ccab36ec57427ba270f444f9108b29f 100644 (file)
@@ -10,25 +10,46 @@ require_once 'application/TimeZone.php';
  */
 class TimeZoneTest extends PHPUnit_Framework_TestCase
 {
+    /**
+     * @var array of timezones
+     */
+    protected $installedTimezones;
+
+    public function setUp()
+    {
+        $this->installedTimezones = [
+            'Antarctica/Syowa',
+            'Europe/London',
+            'Europe/Paris',
+            'UTC'
+        ];
+    }
+
     /**
      * Generate a timezone selection form
      */
     public function testGenerateTimeZoneForm()
     {
-        $generated = generateTimeZoneForm();
+        $expected = [
+            'continents' => [
+                'Antarctica',
+                'Europe',
+                'UTC',
+                'selected' => '',
+            ],
+            'cities' => [
+                ['continent' => 'Antarctica', 'city' => 'Syowa'],
+                ['continent' => 'Europe',     'city' => 'London'],
+                ['continent' => 'Europe',     'city' => 'Paris'],
+                ['continent' => 'UTC',        'city' => 'UTC'],
+                'selected'    => '',
+            ]
+        ];
 
-        // HTML form
-        $this->assertStringStartsWith('Continent:<select', $generated[0]);
-        $this->assertContains('selected="selected"', $generated[0]);
-        $this->assertStringEndsWith('</select><br />', $generated[0]);
+        list($continents, $cities) = generateTimeZoneData($this->installedTimezones);
 
-        // Javascript handler
-        $this->assertStringStartsWith('<script>', $generated[1]);
-        $this->assertContains(
-            '<option value=\"Bermuda\">Bermuda<\/option>',
-            $generated[1]
-        );
-        $this->assertStringEndsWith('</script>', $generated[1]);
+        $this->assertEquals($expected['continents'], $continents);
+        $this->assertEquals($expected['cities'], $cities);
     }
 
     /**
@@ -36,28 +57,26 @@ class TimeZoneTest extends PHPUnit_Framework_TestCase
      */
     public function testGenerateTimeZoneFormPreselected()
     {
-        $generated = generateTimeZoneForm('Antarctica/Syowa');
-
-        // HTML form
-        $this->assertStringStartsWith('Continent:<select', $generated[0]);
-        $this->assertContains(
-            'value="Antarctica" selected="selected"',
-            $generated[0]
-        );
-        $this->assertContains(
-            'value="Syowa" selected="selected"',
-            $generated[0]
-        );
-        $this->assertStringEndsWith('</select><br />', $generated[0]);
+        $expected = [
+            'continents' => [
+                'Antarctica',
+                'Europe',
+                'UTC',
+                'selected' => 'Antarctica',
+            ],
+            'cities' => [
+                ['continent' => 'Antarctica', 'city' => 'Syowa'],
+                ['continent' => 'Europe',     'city' => 'London'],
+                ['continent' => 'Europe',     'city' => 'Paris'],
+                ['continent' => 'UTC',        'city' => 'UTC'],
+                'selected'   => 'Syowa',
+            ]
+        ];
 
+        list($continents, $cities) = generateTimeZoneData($this->installedTimezones, 'Antarctica/Syowa');
 
-        // Javascript handler
-        $this->assertStringStartsWith('<script>', $generated[1]);
-        $this->assertContains(
-            '<option value=\"Bermuda\">Bermuda<\/option>',
-            $generated[1]
-        );
-        $this->assertStringEndsWith('</script>', $generated[1]);
+        $this->assertEquals($expected['continents'], $continents);
+        $this->assertEquals($expected['cities'], $cities);
     }
 
     /**
index 1226148743a038f6c02835644538aa9c08db2ead..7469ab597a69ab4cb468a43e0b8fb6e7d6a0cb98 100644 (file)
         <div class="pure-u-lg-{$ratioLabel} pure-u-1 ">
           <div class="form-label">
             <label>
-              <span class="label-name">{'Timezone'|t}</span>
+              <span class="label-name">{'Timezone'|t}</span><br>
+              <span class="label-desc">{'Continent'|t} &middot; {'City'|t}</span>
             </label>
           </div>
         </div>
         <div class="pure-u-lg-{$ratioInput} pure-u-1 ">
           <div class="form-input">
-            {ignore}FIXME! too hackish, needs to be fixed upstream{/ignore}
-            <div class="timezone" id="timezone-remove">{$timezone_form}</div>
-            <div class="timezone" id="timezone-add"></div>
+            <div class="timezone">
+              <select id="continent" name="continent">
+                {loop="$continents"}
+                  {if="$key !== 'selected'"}
+                    <option value="{$value}" {if="$continents.selected === $value"}selected{/if}>
+                      {$value}
+                    </option>
+                  {/if}
+                {/loop}
+              </select>
+              <select id="city" name="city">
+                {loop="$cities"}
+                  {if="$key !== 'selected'"}
+                    <option value="{$value.city}"
+                            {if="$cities.selected === $value.city"}selected{/if}
+                            data-continent="{$value.continent}">
+                      {$value.city}
+                    </option>
+                  {/if}
+                {/loop}
+              </select>
+            </div>
           </div>
         </div>
       </div>
index 663397ac51f896008b33ecffaafb7f82592db22f..99aca19357f1bdef2d8b24be857a236fa2a1e6b1 100644 (file)
     </div>
 
     <div class="pure-g">
-      <div class="pure-u-lg-{$ratioLabel} pure-u-1 ">
+      <div class="pure-u-lg-{$ratioLabel} pure-u-1">
         <div class="form-label">
-          <label>
-            <span class="label-name">{'Timezone'|t}</span>
+          <label for="title">
+            <span class="label-name">{'Shaarli title'|t}</span>
           </label>
         </div>
       </div>
-      <div class="pure-u-lg-{$ratioInput} pure-u-1 ">
+      <div class="pure-u-lg-{$ratioInput} pure-u-1">
         <div class="form-input">
-          {ignore}FIXME! too hackish, needs to be fixed upstream{/ignore}
-          <div class="timezone" id="timezone-remove">{$timezone_html}</div>
-          <div class="timezone" id="timezone-add"></div>
+          <input type="text" name="title" id="title" placeholder="{'My links'|t}">
         </div>
       </div>
     </div>
     <div class="pure-g">
       <div class="pure-u-lg-{$ratioLabel} pure-u-1">
         <div class="form-label">
-          <label for="title">
-            <span class="label-name">{'Shaarli title'|t}</span>
+          <label>
+            <span class="label-name">{'Timezone'|t}</span><br>
+            <span class="label-desc">{'Continent'|t} &middot; {'City'|t}</span>
           </label>
         </div>
       </div>
       <div class="pure-u-lg-{$ratioInput} pure-u-1">
         <div class="form-input">
-          <input type="text" name="title" id="title" placeholder="{'My links'|t}">
+          <div class="timezone">
+            <select id="continent" name="continent">
+              {loop="$continents"}
+                {if="$key !== 'selected'"}
+                  <option value="{$value}" {if="$continents.selected === $value"}selected{/if}>
+                    {$value}
+                  </option>
+                {/if}
+              {/loop}
+            </select>
+            <select id="city" name="city">
+              {loop="$cities"}
+                {if="$key !== 'selected'"}
+                  <option value="{$value.city}"
+                          {if="$cities.selected === $value.city"}selected{/if}
+                          data-continent="{$value.continent}">
+                    {$value.city}
+                  </option>
+                {/if}
+              {/loop}
+            </select>
+          </div>
         </div>
       </div>
     </div>
index edcf280944a6f723551bf5df011f9228f71588f5..4d47fcd0c2cd4aaf3be8080e84c61782adabd247 100644 (file)
@@ -76,9 +76,12 @@ window.onload = function () {
             }
         }
 
-        document.getElementById('menu-toggle').addEventListener('click', function (e) {
-            toggleMenu();
-        });
+        var menuToggle = document.getElementById('menu-toggle');
+        if (menuToggle != null) {
+            menuToggle.addEventListener('click', function (e) {
+                toggleMenu();
+            });
+        }
 
         window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu);
     })(this, this.document);
@@ -298,21 +301,6 @@ window.onload = function () {
         });
     }
 
-    /**
-     * TimeZome select
-     * FIXME! way too hackish
-     */
-    var toRemove = document.getElementById('timezone-remove');
-    if (toRemove != null) {
-        var firstSelect = toRemove.getElementsByTagName('select')[0];
-        var secondSelect = toRemove.getElementsByTagName('select')[1];
-        toRemove.parentNode.removeChild(toRemove);
-        var toAdd = document.getElementById('timezone-add');
-        var newTimezone = '<span class="timezone-continent">Continent ' + firstSelect.outerHTML + '</span>';
-        newTimezone += ' <span class="timezone-country">Country ' + secondSelect.outerHTML + '</span>';
-        toAdd.innerHTML = newTimezone;
-    }
-
     /**
      * Awesomplete trigger.
      */
@@ -365,6 +353,15 @@ window.onload = function () {
             }
         });
     });
+
+    var continent = document.getElementById('continent');
+    var city = document.getElementById('city');
+    if (continent != null && city != null) {
+        continent.addEventListener('change', function(event) {
+            hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true);
+        });
+        hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false);
+    }
 };
 
 function activateFirefoxSocial(node) {
@@ -390,3 +387,25 @@ function activateFirefoxSocial(node) {
     var activate = new CustomEvent("ActivateSocialFeature");
     node.dispatchEvent(activate);
 }
+
+/**
+ * Add the class 'hidden' to city options not attached to the current selected continent.
+ *
+ * @param cities           List of <option> elements
+ * @param currentContinent Current selected continent
+ * @param reset            Set to true to reset the selected value
+ */
+function hideTimezoneCities(cities, currentContinent, reset = false) {
+    var first = true;
+    [].forEach.call(cities, function(option) {
+        if (option.getAttribute('data-continent') != currentContinent) {
+            option.className = 'hidden';
+        } else {
+            option.className = '';
+            if (reset === true && first === true) {
+                option.setAttribute('selected', 'selected');
+                first = false;
+            }
+        }
+    });
+}
index 704389c596103954ea1ae532b10fd6db5ecaf3bf..7adc7545532cc7d92a0494c25aea111f79292e7c 100644 (file)
@@ -4,7 +4,6 @@
 <body onload="document.configform.title.focus();">
 <div id="pageheader">
   {include="page.header"}
-  {$timezone_js}
   <form method="POST" action="#" name="configform" id="configform">
     <input type="hidden" name="token" value="{$token}">
     <table id="configuration_table">
 
       <tr>
         <td><b>Timezone:</b></td>
-        <td>{$timezone_form}</td>
+        <td>
+          <select id="continent" name="continent">
+            {loop="$continents"}
+              {if="$key !== 'selected'"}
+                <option value="{$value}" {if="$continents.selected === $value"}selected{/if}>
+                  {$value}
+                </option>
+              {/if}
+            {/loop}
+          </select>
+          <select id="city" name="city">
+            {loop="$cities"}
+              {if="$key !== 'selected'"}
+                <option value="{$value.city}"
+                        {if="$cities.selected === $value.city"}selected{/if}
+                        data-continent="{$value.continent}">
+                  {$value.city}
+                </option>
+              {/if}
+            {/loop}
+          </select>
+        </td>
       </tr>
 
       <tr>
index 7ca567e7549f5b3c729673a38c8e8455bfd6ddf9..9c72d9938bca0dd6750daf950c778b5c0cb8ae6d 100644 (file)
@@ -41,6 +41,10 @@ strong {
     font-weight: bold;
 }
 
+.hidden {
+    display: none;
+}
+
 /* Buttons */
 .bigbutton, #pageheader a.bigbutton  {
     background-color: #c0c0c0;
index 42874dcdb42c61963050599c6df922a079b615f9..aca890d6c3a549fca924fa02a58a5fa384a7dae6 100644 (file)
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <html>
-<head>{include="includes"}{$timezone_js}</head>
+<head>{include="includes"}</head>
 <body onload="document.installform.setlogin.focus();">
 <div id="install">
     <h1>Shaarli</h1>
@@ -9,7 +9,31 @@
         <table>
             <tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr>
             <tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr>
-            {$timezone_html}
+            <tr>
+                <td><b>Timezone:</b></td>
+                <td>
+                    <select id="continent" name="continent">
+                        {loop="$continents"}
+                        {if="$key !== 'selected'"}
+                        <option value="{$value}" {if="$continents.selected === $value"}selected{/if}>
+                        {$value}
+                        </option>
+                        {/if}
+                        {/loop}
+                    </select>
+                    <select id="city" name="city">
+                        {loop="$cities"}
+                        {if="$key !== 'selected'"}
+                        <option value="{$value.city}"
+                                {if="$cities.selected === $value.city"}selected{/if}
+                        data-continent="{$value.continent}">
+                        {$value.city}
+                        </option>
+                        {/if}
+                        {/loop}
+                    </select>
+                </td>
+            </tr>
             <tr><td><b>Page title:</b></td><td><input type="text" name="title" size="30"></td></tr>
             <tr><td valign="top"><b>Update:</b></td><td>
                 <input type="checkbox" name="updateCheck" id="updateCheck" checked="checked"><label for="updateCheck">&nbsp;Notify me when a new release is ready</label></td>
diff --git a/tpl/vintage/js/shaarli.js b/tpl/vintage/js/shaarli.js
new file mode 100644 (file)
index 0000000..9bcc96f
--- /dev/null
@@ -0,0 +1,32 @@
+window.onload = function () {
+    var continent = document.getElementById('continent');
+    var city = document.getElementById('city');
+    if (continent != null && city != null) {
+        continent.addEventListener('change', function(event) {
+            hideTimezoneCities(city, continent.options[continent.selectedIndex].value, true);
+        });
+        hideTimezoneCities(city, continent.options[continent.selectedIndex].value, false);
+    }
+};
+
+/**
+ * Add the class 'hidden' to city options not attached to the current selected continent.
+ *
+ * @param cities           List of <option> elements
+ * @param currentContinent Current selected continent
+ * @param reset            Set to true to reset the selected value
+ */
+function hideTimezoneCities(cities, currentContinent, reset = false) {
+    var first = true;
+    [].forEach.call(cities, function(option) {
+        if (option.getAttribute('data-continent') != currentContinent) {
+            option.className = 'hidden';
+        } else {
+            option.className = '';
+            if (reset === true && first === true) {
+                option.setAttribute('selected', 'selected');
+                first = false;
+            }
+        }
+    });
+}
index 006d1d683b465d303ae56c4332d659bedab0533b..4ce0803a064dcbf3a78efed3043566b7986cf1ca 100644 (file)
@@ -26,6 +26,7 @@
 <script>function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>
 {/if}
 
+<script src="js/shaarli.js"></script>
 {loop="$plugins_footer.js_files"}
        <script src="{$value}#"></script>
 {/loop}