Load all category CSS once when loading the application to avoid missing category colors.

This commit is contained in:
Nathan Gray 2015-10-15 17:28:56 +00:00
parent 9dd37010d4
commit 8b42f6aeb8
7 changed files with 99 additions and 57 deletions

View File

@ -573,8 +573,8 @@ class admin_categories
if($tmpl instanceof etemplate_widget_template) if($tmpl instanceof etemplate_widget_template)
{ {
// Send categories for row colors // Category styles
$sel_options['cat_id'] = etemplate_widget_menupopup::typeOptions('select-cat', ',,,'.$appname.',0'); egw_framework::includeCSS('/phpgwapi/categories.php?app='.$appname);
} }
$tmpl->exec($this->list_link,$content,$sel_options,$readonlys,array( $tmpl->exec($this->list_link,$content,$sel_options,$readonlys,array(

View File

@ -221,6 +221,9 @@ class etemplate_new extends etemplate_widget_template
{ {
egw_framework::validate_file('.','app',$app,false); egw_framework::validate_file('.','app',$app,false);
} }
// Category styles
egw_framework::includeCSS('/phpgwapi/categories.php?app='.$app);
// set action attribute for autocomplete form tag // set action attribute for autocomplete form tag
// as firefox complains on about:balnk action, thus we have to literaly submit the form to a blank html // as firefox complains on about:balnk action, thus we have to literaly submit the form to a blank html
$form_action = "about:blank"; $form_action = "about:blank";

View File

@ -515,58 +515,14 @@ var et2_nextmatch_rowProvider = ClassWithAttributes.extend(
cats = classes.match(this.cat_regexp) || []; cats = classes.match(this.cat_regexp) || [];
classes = classes.replace(this.cat_regexp, ''); classes = classes.replace(this.cat_regexp, '');
// Get category info // Set category class
if(!this.categories) for(var i = 0; i < cats.length; i++)
{
// Nextmatch category filter should put them here
var categories = _mgrs["sel_options"].getEntry('cat_id');
// Or they are in the global - 1 level up
if(!categories) categories = _mgrs["sel_options"].parentMgr.getEntry('cat_id');
// If not using category (tracker, calendar list) look for sel_options in the rows
if(!categories) categories = _mgrs["sel_options"].parentMgr.getEntry(category_location);
if(!categories) categories = _mgrs["sel_options"].getEntry("${row}["+category_location + "]");
// Cache
if(categories)
{
if (!jQuery.isArray(categories))
{
this.categories = categories;
}
else
{
this.categories = {};
for(var i=0; i < categories.length; ++i)
{
var cat = categories[i];
this.categories[cat.value] = cat;
}
}
}
}
for(var i = 0; i < cats.length && this.categories; i++)
{ {
// Need cat_, classes can't start with a number // Need cat_, classes can't start with a number
var cat_id = cats[i].replace(this.cat_cleanup, ''); var cat_id = cats[i].replace(this.cat_cleanup, '');
var cat_class = 'cat_'+cat_id; var cat_class = 'cat_'+cat_id;
// Check for existing class classes += ' '+cat_class;
// TODO
var cat = this.categories[cat_id] || null;
for(var j = 0; cat == null && this.categories && j < this.categories.length; j++)
{
if(this.categories[j] && this.categories[j].value && this.categories[j].value == cat_id)
{
cat = this.categories[j];
}
}
// Create class
if(cat && cat.color)
{
this._rootWidget.egw().css('.'+cat_class, "background-color: " + cat.color + ";");
classes += ' '+cat_class;
}
} }
classes += " row_category"; classes += " row_category";
} }

View File

@ -306,13 +306,15 @@ var et2_selectbox = et2_inputWidget.extend(
if(option_data.icon) if(option_data.icon)
{ {
var img = this.egw().image(option_data.icon); var img = this.egw().image(option_data.icon);
jQuery(document.createElement("img")) jQuery(document.createElement(img ? "img" : "div"))
.attr("src", img) .attr("src", img)
.addClass('cat_icon cat_' + _value)
.appendTo(label); .appendTo(label);
} }
if(option_data.color) if(option_data.color)
{ {
label.css("background-color",option_data.color); label.css("background-color",option_data.color)
.addClass('cat_' + _value);
} }
} }
label.append(jQuery("<span>"+_label+"</span>")); label.append(jQuery("<span>"+_label+"</span>"));

View File

@ -368,9 +368,12 @@ button#cancel {
.et2_selectbox input[type="checkbox"] { .et2_selectbox input[type="checkbox"] {
margin: 3px; margin: 3px;
} }
.et2_selectbox .ui-multiselect-checkboxes img { .et2_selectbox .ui-multiselect-checkboxes img, .et2_selectbox .ui-multiselect-checkboxes div {
float: right; float: right;
height: 1.8em; height: 1.8em;
width: 1.8em;
background-size: contain;
background-repeat: no-repeat;
} }
.et2_selectbox .ui-multiselect-checkboxes div.ui-icon-close { .et2_selectbox .ui-multiselect-checkboxes div.ui-icon-close {
visibility: hidden; visibility: hidden;

71
phpgwapi/categories.php Normal file
View File

@ -0,0 +1,71 @@
<?php
/**
* API: loading categories and setting styles
*
* Usage: /egroupware/phpgwapi/categories.php[?app=calendar]
*
* @link www.egroupware.org
* @author Nathan Gray
* @package API
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @version $Id$
*/
// switch evtl. set output-compression off, as we cant calculate a Content-Length header with transparent compression
ini_set('zlib.output_compression', 0);
$GLOBALS['egw_info'] = array(
'flags' => array(
'currentapp' => 'preferences',
'noheader' => true,
'nocachecontrol' => true,
)
);
include '../header.inc.php';
// Get appname
$appname = $_GET['app'] && $GLOBALS['egw_info']['apps'][$_GET['app']] ? $_GET['app'] : categories::GLOBAL_APPNAME;
$cats = new categories('', $appname);
$categories = $cats->return_array('all',0, false, '', 'ASC','',$appname==categories::GLOBAL_APPNAME);
$content = "/* Category CSS for $appname */\n\n";
foreach($categories as $cat)
{
if($cat['data']['color'])
{
$content .= ".cat_{$cat['id']} { background-color: {$cat['data']['color']};} /*{$cat['name']}*/\n";
}
if($cat['data']['icon'])
{
$content .= ".cat_{$cat['id']} .cat_icon { background-image: url('". admin_categories::icon_url($cat['data']['icon']) ."');} /*{$cat['name']}*/\n";
}
}
// use an etag over categories
$etag = '"'.md5($content).'"';
// headers to allow caching, egw_framework specifies etag on url to force reload, even with Expires header
egw_session::cache_control(86400); // cache for 1 day
Header('Content-Type: text/css; charset=utf-8');
Header('ETag: '.$etag);
// if servers send a If-None-Match header, response with 304 Not Modified, if etag matches
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag)
{
header("HTTP/1.1 304 Not Modified");
common::egw_exit();
}
// we run our own gzip compression, to set a correct Content-Length of the encoded content
if (in_array('gzip', explode(',',$_SERVER['HTTP_ACCEPT_ENCODING'])) && function_exists('gzencode'))
{
$content = gzencode($content);
header('Content-Encoding: gzip');
}
// Content-Lenght header is important, otherwise browsers dont cache!
Header('Content-Length: '.bytes($content));
echo $content;

View File

@ -1385,6 +1385,9 @@ abstract class egw_framework
// eTemplate2 - load in top so sidebox has styles too // eTemplate2 - load in top so sidebox has styles too
self::includeCSS('/etemplate/templates/default/etemplate2.css'); self::includeCSS('/etemplate/templates/default/etemplate2.css');
// Category styles
self::includeCSS('/phpgwapi/categories.php');
// For mobile user-agent we prefer mobile theme over selected one with a final fallback to theme named as template // For mobile user-agent we prefer mobile theme over selected one with a final fallback to theme named as template
$themes_to_check = array(); $themes_to_check = array();
if (html::$ua_mobile) $themes_to_check[] = $this->template_dir.'/css/mobile.css'; if (html::$ua_mobile) $themes_to_check[] = $this->template_dir.'/css/mobile.css';
@ -1418,11 +1421,13 @@ abstract class egw_framework
{ {
foreach(self::resolve_css_includes($path) as $path) foreach(self::resolve_css_includes($path) as $path)
{ {
if (($mod = filemtime(EGW_SERVER_ROOT.$path)) > $max_modified) $max_modified = $mod; list($file,$query) = explode('?',$path,2);
if (($mod = filemtime(EGW_SERVER_ROOT.$file)) > $max_modified) $max_modified = $mod;
if ($debug_minify || substr($path, -8) == '/app.css') // do NOT include app.css, as it changes from app to app // do NOT include app.css or categories.php, as it changes from app to app
if ($debug_minify || substr($path, -8) == '/app.css' || substr($file,-14) == 'categories.php')
{ {
$css_files .= '<link href="'.$GLOBALS['egw_info']['server']['webserver_url'].$path.'?'.$mod.'" type="text/css" rel="StyleSheet" />'."\n"; $css_files .= '<link href="'.$GLOBALS['egw_info']['server']['webserver_url'].$path.($query ? '&' : '?').$mod.'" type="text/css" rel="StyleSheet" />'."\n";
} }
else else
{ {
@ -1454,7 +1459,9 @@ abstract class egw_framework
protected static function resolve_css_includes($path, &$pathes=array()) protected static function resolve_css_includes($path, &$pathes=array())
{ {
$matches = null; $matches = null;
if (($to_check = file_get_contents (EGW_SERVER_ROOT.$path, false, null, -1, 1024)) &&
list($file,$query) = explode('?',$path,2);
if (($to_check = file_get_contents (EGW_SERVER_ROOT.$file, false, null, -1, 1024)) &&
stripos($to_check, '/*@import') !== false && preg_match_all('|/\*@import url\("([^"]+)"|i', $to_check, $matches)) stripos($to_check, '/*@import') !== false && preg_match_all('|/\*@import url\("([^"]+)"|i', $to_check, $matches))
{ {
foreach($matches[1] as $import_path) foreach($matches[1] as $import_path)
@ -2248,7 +2255,7 @@ abstract class egw_framework
{ {
$path = $app; $path = $app;
} }
if (!file_exists(EGW_SERVER_ROOT.$path)) if (!file_exists(EGW_SERVER_ROOT.$path) && !file_exists(EGW_SERVER_ROOT . parse_url($path,PHP_URL_PATH)))
{ {
//error_log(__METHOD__."($app,$name) $path NOT found!"); //error_log(__METHOD__."($app,$name) $path NOT found!");
return false; return false;