Swapped in a new theme selector.
authorDan
Fri, 20 Mar 2009 09:13:17 -0400
changeset 870 82bbfe3dc8a0
parent 869 58bc29c14a4d
child 871 4e45f191dc33
Swapped in a new theme selector.
ajax.php
images/check-large.png
includes/clientside/static/ajax.js
language/english/core.json
--- a/ajax.php	Wed Mar 18 11:35:28 2009 -0400
+++ b/ajax.php	Fri Mar 20 09:13:17 2009 -0400
@@ -540,30 +540,78 @@
       $parms = ( isset($_POST['acl_params']) ) ? rawurldecode($_POST['acl_params']) : false;
       echo PageUtils::acl_json($parms);
       break;
+    case 'theme_list':
+      header('Content-type: application/json');
+      
+      $q = $db->sql_query('SELECT theme_name, theme_id FROM ' . table_prefix . "themes WHERE enabled = 1 ORDER BY theme_name ASC;");
+      if ( !$q )
+        $db->die_json();
+      
+      $return = array();
+      while ( $row = $db->fetchrow() )
+        $return[] = $row;
+      
+      foreach ( $return as &$theme )
+      {
+        $theme['have_thumb'] = file_exists(ENANO_ROOT . "/themes/{$theme['theme_id']}/preview.png");
+      }
+      
+      echo enano_json_encode($return);
+      
+      break;
+    case "get_styles":
+      if ( !preg_match('/^[a-z0-9_-]+$/', $_GET['theme_id']) )
+        die(enano_json_encode(array()));
+      
+      $theme_id = $_GET['theme_id'];
+      $return = array();
+      
+      if ( $dr = @opendir(ENANO_ROOT . "/themes/$theme_id/css/") )
+      {
+        while ( $dh = @readdir($dr) )
+        {
+          if ( preg_match('/\.css$/', $dh) && $dh != '_printable.css' )
+          {
+            $return[] = preg_replace('/\.css$/', '', $dh);
+          }
+        }
+      }
+      else
+      {
+        $return = array(
+            'mode' => 'error',
+            'error' => 'Could not open directory.'
+          );
+      }
+      echo enano_json_encode($return);
+      break;
     case "change_theme":
       if ( !isset($_POST['theme_id']) || !isset($_POST['style_id']) )
       {
-        die('Invalid input');
+        die(enano_json_encode(array('mode' => 'error', 'error' => 'Invalid parameter')));
       }
       if ( !preg_match('/^([a-z0-9_-]+)$/i', $_POST['theme_id']) || !preg_match('/^([a-z0-9_-]+)$/i', $_POST['style_id']) )
       {
-        die('Invalid input');
+        die(enano_json_encode(array('mode' => 'error', 'error' => 'Invalid parameter')));
       }
       if ( !file_exists(ENANO_ROOT . '/themes/' . $_POST['theme_id'] . '/css/' . $_POST['style_id'] . '.css') )
       {
-        die('Can\'t find theme file: ' . ENANO_ROOT . '/themes/' . $_POST['theme_id'] . '/css/' . $_POST['style_id'] . '.css');
+        die(enano_json_encode(array('mode' => 'error', 'error' => 'Can\'t find theme file: ' . ENANO_ROOT . '/themes/' . $_POST['theme_id'] . '/css/' . $_POST['style_id'] . '.css')));;
       }
       if ( !$session->user_logged_in )
       {
-        die('You must be logged in to change your theme');
+        die(enano_json_encode(array('mode' => 'error', 'error' => 'You must be logged in to change your theme')));
       }
       // Just in case something slipped through...
       $theme_id = $db->escape($_POST['theme_id']);
       $style_id = $db->escape($_POST['style_id']);
-      $e = $db->sql_query('UPDATE ' . table_prefix . "users SET theme='$theme_id', style='$style_id' WHERE user_id=$session->user_id;");
+      $e = $db->sql_query('UPDATE ' . table_prefix . "users SET theme = '$theme_id', style = '$style_id' WHERE user_id = $session->user_id;");
       if ( !$e )
         die( $db->get_error() );
-      die('GOOD');
+      
+      echo enano_json_encode(array(
+          'success' => true
+        ));
       break;
     case 'get_tags':
       
Binary file images/check-large.png has changed
--- a/includes/clientside/static/ajax.js	Wed Mar 18 11:35:28 2009 -0400
+++ b/includes/clientside/static/ajax.js	Fri Mar 20 09:13:17 2009 -0400
@@ -155,7 +155,6 @@
     return false;
   
   var input = obj.getElementsByTagName('input')[0];
-  console.debug(obj, input);
   if ( !input )
     return false;
   var newname = input.value;
@@ -738,142 +737,170 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  load_component(['l10n', 'messagebox', 'flyin', 'fadefilter']);
+  load_component(['l10n', 'fadefilter', 'jquery', 'jquery-ui']);
+  
+  // force string fetch
+  $lang.get('etc_cancel');
+  
+  // preload some images
+  var i1 = new Image();
+  i1.src = cdnPath + '/images/loading-big.gif';
+  var i2 = new Image();
+  i2.src = cdnPath + '/images/check-large.png';
+  
+  darken(true, 70, 'theme-selector-shade');
+  
+  $('body').append('<div id="theme-selector-wrapper"><div id="theme-selector-body"><div id="theme-selector-inner"><div class="theme-selector-spinner"></div></div></div></div>');
+  $('#theme-selector-wrapper')
+    .css('top', String(getScrollOffset()) + 'px')
+    .css('z-index', String( getHighestZ() + 20 ));
   
-  var inner_html = '';
-  inner_html += '<p><label>' + $lang.get('ajax_changestyle_lbl_theme') + ' ';
-  inner_html += '  <select id="chtheme_sel_theme" onchange="ajaxGetStyles(this.value);">';
-  inner_html += '    <option value="_blank" selected="selected">' + $lang.get('ajax_changestyle_select') + '</option>';
-  inner_html +=      ENANO_THEME_LIST;
-  inner_html += '  </select>';
-  inner_html += '</label></p>';
-  var chtheme_mb = new MessageBox(MB_OKCANCEL|MB_ICONQUESTION, $lang.get('ajax_changestyle_title'), inner_html);
-  chtheme_mb.onbeforeclick['OK'] = ajaxChangeStyleComplete;
+  $.get(stdAjaxPrefix + '&_mode=theme_list', {}, function(data, status)
+    {
+      $('#theme-selector-inner .theme-selector-spinner').fadeOut(650);
+      $('#theme-selector-body').animate({ width: 708 }, 600, function()
+        {
+          // avoiding jQuery's fade functions because they insist on toggling display as well
+          changeOpac(0, 'theme-selector-inner');
+          $('#theme-selector-inner').html('<h3></h3>');
+          $('#theme-selector-inner > h3').text($lang.get('ajax_thmsel_lbl_choosetheme'));
+          $('#theme-selector-inner').append('<ul></ul>');
+          for ( var i = 0; i < data.length; i++ )
+          {
+            var bgi = data[i].have_thumb ? cdnPath + '/themes/' + data[i].theme_id + '/preview.png' : cdnPath + '/images/themepreview.png';
+            $('#theme-selector-inner > ul').append('<li id="theme_' + i + '"><a href="#"><span></span></a></li>');
+            $('#theme-selector-inner li#theme_' + i + ' > a')
+              .css('background-image', 'url(' + bgi + ')')
+              .attr('enano:theme_id', data[i].theme_id);
+            $('#theme-selector-inner li#theme_' + i + ' > a > span')
+              .text(data[i].theme_name);
+          }
+          $('#theme-selector-inner').append('<span class="menuclear"></span>');
+          $('#theme-selector-inner').append('<div style="padding-top: 40px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('etc_cancel') + '</a></div>');
+          
+          $('#theme-selector-body').animate({ height: $('#theme-selector-inner').height() + 30 }, 600, function()
+            {
+              opacity('theme-selector-inner', 0, 100, 750);
+            });
+          
+          $('#theme-selector-inner li a').click(function()
+            {
+              var theme_id = $(this).attr('enano:theme_id');
+              $('span', this).html('&nbsp;').addClass('loading').fadeTo('fast', 0.6)
+              $.get(stdAjaxPrefix + '&_mode=get_styles', { theme_id: theme_id }, function(data, status)
+                {
+                  if ( data.length > 1 )
+                  {
+                    $('#theme-selector-inner').css('height', $('#theme-selector-inner').height()).fadeOut(600, function()
+                    {
+                      var div = document.createElement('div');
+                      domObjChangeOpac(0, div);
+                      
+                      $(div).attr('id', 'theme-selector-style-list').append('<h3></h3>');
+                      $('h3', div).text($lang.get('ajax_thmsel_lbl_choosestyle'));
+                      
+                      for ( var i = 0; i < data.length; i++ )
+                      {
+                        $(div).append('<a class="abutton block stylebtn" id="stylebtn_' + i + '" enano:style_id="' + data[i] + '">' + themeid_to_title(data[i]) + '</a>');
+                      }
+                      
+                      $(div).append('<div style="padding-top: 40px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('etc_cancel') + '</a></div>');
+                      
+                      changeOpac(0, 'theme-selector-style-list');
+                      $(this).html(div).show();
+                      
+                      $('#theme-selector-body').animate({width: 300, height: $('#theme-selector-style-list').height() + 30}, 300, function()
+                        {
+                          opacity('theme-selector-style-list', 0, 100, 500);
+                        });
+                      
+                      $('.stylebtn').click(function()
+                        {
+                          ajaxChangeThemeSetLoading();
+                          $.post(stdAjaxPrefix + '&_mode=change_theme', { theme_id: theme_id, style_id: $(this).attr('enano:style_id') }, function(data, status)
+                            {
+                              if ( data.error )
+                              {
+                                alert(data.error);
+                                ajaxChangeStyleClose();
+                                return false;
+                              }
+                              ajaxChangeThemeShowSuccess();
+                            }, 2000);
+                          
+                          return false;
+                        });
+                    });
+                  }
+                  else
+                  {
+                    if ( !data[0] )
+                    {
+                      alert('Didn\'t find any CSS files. :-/');
+                      ajaxChangeStyleClose();
+                    }
+                    
+                    $.post(stdAjaxPrefix + '&_mode=change_theme', { theme_id: theme_id, style_id: data[0] }, function(data, status)
+                      {
+                        if ( data.error )
+                        {
+                          alert(data.error);
+                          ajaxChangeStyleClose();
+                          return false;
+                        }
+                        ajaxChangeThemeShowSuccess();
+                      }, 'json');
+                  }
+                }, 'json');
+              return false;
+            }); // click function
+        }); // animate
+    }, 'json'); // get
 }
 
-window.ajaxGetStyles = function(id)
+window.ajaxChangeThemeSetLoading = function()
 {
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  var thediv = document.getElementById('chtheme_sel_style_parent');
-  if ( thediv )
-  {
-    thediv.parentNode.removeChild(thediv);
-  }
-  if ( id == '_blank' )
-  {
-    return null;
-  }
-  ajaxGet(stdAjaxPrefix + '&_mode=getstyles&id=' + id, function(ajax) {
-      if ( ajax.readyState == 4 && ajax.status == 200 )
+  $('#theme-selector-body').animate({width: 130, height: 130});
+  $('#theme-selector-inner').empty().html('<div class="theme-selector-spinner"></div>');
+}
+
+window.ajaxChangeThemeShowSuccess = function()
+{
+  $('#theme-selector-body').animate({width: 400, height: 300 }, 600, function()
       {
-        // IE doesn't like substr() on ajax.responseText
-        var response = String(ajax.responseText + '');
-        if ( response.substr(0,1) != '[' )
-        {
-          alert('Invalid or unexpected JSON response from server:\n' + response);
-          return null;
-        }
-        
-        // Build a selector and matching label
-        var data = parseJSON(response);
-        var options = new Array();
-        for( var i in data )
-        {
-          var item = data[i];
-          var title = themeid_to_title(item);
-          var option = document.createElement('option');
-          option.value = item;
-          option.appendChild(document.createTextNode(title));
-          options.push(option);
-        }
-        var p_parent = document.createElement('p');
-        var label  = document.createElement('label');
-        p_parent.id = 'chtheme_sel_style_parent';
-        label.appendChild(document.createTextNode($lang.get('ajax_changestyle_lbl_style') + ' '));
-        var select = document.createElement('select');
-        select.id = 'chtheme_sel_style';
-        for ( var i in options )
-        {
-          select.appendChild(options[i]);
-        }
-        label.appendChild(select);
-        p_parent.appendChild(label);
-        
-        // Stick it onto the messagebox
-        var div = document.getElementById('messageBox');
-        var kid = div.firstChild.nextSibling;
-        
-        kid.appendChild(p_parent);
-        
-      }
-    }, true);
+        $('#theme-selector-inner').append('<img src="' + cdnPath + '/images/check-large.png" alt=" " style="display: block; margin: 15px auto;" />');
+        $('#theme-selector-inner').append('<h3>' + $lang.get('ajax_thmsel_msg_success') + '</h3>');
+        $('#theme-selector-inner').append('<div style="padding-top: 20px;"><a class="abutton abutton_green" style="font-size: larger;" href="#" onclick="window.location.reload(); return false;">' + $lang.get('ajax_thmsel_btn_reload') + '</a></div>');
+        $('#theme-selector-inner').append('<div style="padding-top: 25px;"><a href="#" style="font-size: smaller;" onclick="ajaxChangeStyleClose(); return false;">' + $lang.get('ajax_thmsel_btn_close') + '</a><br /><small>' + $lang.get('ajax_thmsel_btn_close_hint') + '</small></div>');
+        $('#theme-selector-inner').fadeIn();
+      });
+  setTimeout(function()
+    {
+      $('#theme-selector-inner').empty();
+    }, 10);
 }
 
-window.ajaxChangeStyleComplete = function()
+window.ajaxChangeStyleClose = function()
 {
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  var theme = $dynano('chtheme_sel_theme');
-  var style = $dynano('chtheme_sel_style');
-  if ( !theme.object || !style.object )
-  {
-    alert($lang.get('ajax_changestyle_pleaseselect_theme'));
-    return true;
-  }
-  var theme_id = theme.object.value;
-  var style_id = style.object.value;
-  
-  if ( typeof(theme_id) != 'string' || typeof(style_id) != 'string' )
-  {
-    alert('Couldn\'t get theme or style ID');
-    return true;
-  }
-  
-  if ( theme_id.length < 1 || style_id.length < 1 )
-  {
-    alert('Theme or style ID is zero length');
-    return true;
-  }
-  
-  ajaxPost(stdAjaxPrefix + '&_mode=change_theme', 'theme_id=' + ajaxEscape(theme_id) + '&style_id=' + ajaxEscape(style_id), function(ajax)
+  setTimeout(function()
     {
-      if ( ajax.readyState == 4 && ajax.status == 200 )
-      {
-        if ( ajax.responseText == 'GOOD' )
+      enlighten(false, 'theme-selector-shade');
+      $('#theme-selector-wrapper').fadeOut(500, function()
         {
-          var c = confirm($lang.get('ajax_changestyle_success'));
-          if ( c )
-            window.location.reload();
-        }
-        else
-        {
-          alert('Error occurred during attempt to change theme:\n' + ajax.responseText);
-        }
-      }
-    }, true);
-  
-  return false;
-  
+          $(this).remove();
+        });
+    }, 300);
+  opacity('theme-selector-inner', 100, 0, 250);
 }
 
-window.ajaxSwapCSS = function()
+function themeid_to_title(id)
 {
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  setAjaxLoading();
-  if(_css) {
-    document.getElementById('mdgCss').href = main_css;
-    _css = false;
-  } else {
-    document.getElementById('mdgCss').href = print_css;
-    _css = true;
-  }
-  unsetAjaxLoading();
-  menuOff();
+  if ( typeof(id) != 'string' )
+    return false;
+  id = id.substr(0, 1).toUpperCase() + id.substr(1);
+  id = id.replace(/_/g, ' ');
+  id = id.replace(/-/g, ' ');
+  return id;
 }
 
 window.ajaxSetPassword = function()
@@ -1565,12 +1592,3 @@
     });
 }
 
-function themeid_to_title(id)
-{
-  if ( typeof(id) != 'string' )
-    return false;
-  id = id.substr(0, 1).toUpperCase() + id.substr(1);
-  id = id.replace(/_/g, ' ');
-  id = id.replace(/-/g, ' ');
-  return id;
-}
--- a/language/english/core.json	Wed Mar 18 11:35:28 2009 -0400
+++ b/language/english/core.json	Fri Mar 20 09:13:17 2009 -0400
@@ -1,6 +1,6 @@
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.1.1
+ * Version 1.1.6 (Caoineag beta 1)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -40,7 +40,7 @@
       tz: 'Time zones',
       plural: 's',
       enano_about_th: 'About the Enano Content Management System',
-      enano_about_poweredby: '<p>This website is powered by <a href="http://enanocms.org/">Enano</a>, the lightweight and open source CMS that everyone can use. Enano is copyright &copy; 2006-2007 Dan Fuhry. For legal information, along with a list of libraries that Enano uses, please see <a href="http://enanocms.org/Legal_information">Legal Information</a>.</p><p>The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified, distributed, and used to create derivative works. For more information about Free Software, check out the <a href="http://en.wikipedia.org/wiki/Free_Software" onclick="window.open(this.href); return false;">Wikipedia page</a> or the <a href="http://www.fsf.org/" onclick="window.open(this.href); return false;">Free Software Foundation\'s</a> homepage.</p>',
+      enano_about_poweredby: '<p>This website is powered by <a href="http://enanocms.org/">Enano</a>, the lightweight and open source CMS that everyone can use. Enano is copyright &copy; 2006-2009 Dan Fuhry. For legal information, along with a list of libraries that Enano uses, please see <a href="http://enanocms.org/Legal_information">Legal Information</a>.</p><p>The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified, distributed, and used to create derivative works. For more information about Free Software, check out the <a href="http://en.wikipedia.org/wiki/Free_Software" onclick="window.open(this.href); return false;">Wikipedia page</a> or the <a href="http://www.fsf.org/" onclick="window.open(this.href); return false;">Free Software Foundation\'s</a> homepage.</p>',
       enano_about_gpl: '<p>This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p><p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.</p><p>You should have received <a href="%gpl_link%">a copy of the GNU General Public License</a> along with this program; if not, write to:</p><p style="margin-left 2em;">Free Software Foundation, Inc.,<br />51 Franklin Street, Fifth Floor<br />Boston, MA 02110-1301, USA</p><p>Alternatively, you can <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">read it online</a>.</p>',
       enano_about_lbl_enanoversion: '<a href="http://enanocms.org">Enano</a> version:',
       enano_about_lbl_webserver: 'Web server:',
@@ -258,6 +258,13 @@
       lbl_page_category: 'category',
       lbl_page_external: 'external page',
       
+      lbl_sitetools: 'site tools',
+      lbl_changes: 'changes',
+      
+      btn_changes_mine: 'mine',
+      btn_changes_recent: 'recent',
+      btn_changes_history: 'this page',
+      
       btn_discussion: 'discussion (%num_comments%)',
       btn_discussion_unapp: '<span title="Approved: %num_app% | Unapproved: %num_unapp% | Spam: %num_spam%">discussion (%num_comments%) [!]</span>',
       btn_edit: 'edit this page',
@@ -474,17 +481,18 @@
       clearlogs_confirm_title: 'Clear this page\'s logs?',
       clearlogs_confirm_body: 'This will erase this page\'s entire history and is an irreversible operation.',
       clearlogs_btn_submit: 'Clear Logs',
-      changestyle_select: '[Select]',
-      changestyle_title: 'Change your theme',
-      changestyle_pleaseselect_theme: 'Please select a theme from the list.',
-      changestyle_lbl_theme: 'Theme:',
-      changestyle_lbl_style: 'Style:',
-      changestyle_success: 'Your theme preference has been changed.\nWould you like to reload the page now to see the changes?',
       killphp_confirm: 'Are you really sure you want to do this? Some pages might not function if this emergency-only feature is activated.',
       killphp_success: 'Embedded PHP in pages has been disabled.',
       lbl_moreoptions_nojs: 'More options for this page',
       msg_loading_component: 'Loading %component%...',
       
+      thmsel_lbl_choosetheme: 'Choose a theme',
+      thmsel_lbl_choosestyle: 'Choose a style variation',
+      thmsel_msg_success: 'Theme changed',
+      thmsel_btn_reload: 'Reload page',
+      thmsel_btn_close: 'Close selector and reload later',
+      thmsel_btn_close_hint: 'You will see your new theme choice go into effect the next time you refresh this page.',
+      
       badjson_title: 'The site encountered an error while processing your request.',
       badjson_body: 'We unexpectedly received the following response from the server. The response should have been in the JSON serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers for this problem:',
       badjson_tip1: 'The server sent back a bad HTTP response code and thus sent an error page instead of running Enano. This indicates a possible problem with your server, and is not likely to be a bug with Enano.',
@@ -529,6 +537,7 @@
       btn_userpage: 'User page',
       btn_mycontribs: 'My contributions',
       btn_preferences: 'Preferences',
+      btn_preferences_short: 'User CP',
       btn_privatemessages: 'Private messages',
       btn_groupcp: 'Group control panel',
       btn_register: 'Create an account',