Refactoring a CMS to Use Shared LITTLED Libraries: Difference between revisions
Jump to navigation
Jump to search
| (13 intermediate revisions by 2 users not shown) | |||
| Line 4: | Line 4: | ||
*AJAX scripts | *AJAX scripts | ||
**Listings: <code>/_hostmgr/[CONTENT]/_ajax/listings.php</code> | **Listings: <code>/_hostmgr/_ajax/utils/listings.php</code> or <code>/_hostmgr/[CONTENT]/_ajax/listings.php</code> | ||
**Delete: <code>/_hostmgr/_ajax/utils/delete_record.php</code> | **Delete: <code>/_hostmgr/_ajax/utils/delete_record.php</code> | ||
**Update cache: <code>/_hostmgr/_ajax/utils/update_cache.php</code> | **Update cache: <code>/_hostmgr/_ajax/utils/update_cache.php</code> | ||
| Line 33: | Line 33: | ||
*Refer to a class that’s been refactored for logic updates within the class’s routines. | *Refer to a class that’s been refactored for logic updates within the class’s routines. | ||
*Use <code>filter_collection_class</code> as base class for any class that represents records in the database. | *Use <code>filter_collection_class</code> as base class for any class that represents records in the database. | ||
*Add <code>$site_section</code> property to any class that handles listings and pagination.<br/> | *Add <code>$site_section</code> property to any class that handles listings and pagination.<br/>TODO: Consider making this a property of <code>filter_collection_class</code>. | ||
TODO: Consider making this a property of <code>filter_collection_class</code>. | *Add <code>$section_operations</code> property to any class that handles listings and pagination.<br/>TODO: Consider making this a property of <code>filter_collection_class</code>. | ||
===Add content handlers to PHP cache and resort classes=== | ===Add content handlers to PHP cache and resort classes=== | ||
| Line 68: | Line 68: | ||
===Local JavaScript libraries=== | ===Local JavaScript libraries=== | ||
*Minify existing libraries | * Minify existing libraries | ||
**Created “source” version of existing libraries: <code>lib.js</code> > <code>lib-source.js</code> | ** Created “source” version of existing libraries: <code>lib.js</code> > <code>lib-source.js</code> | ||
**Compress existing libraries: http://javascriptcompressor.com/ | ** Compress existing libraries: http://javascriptcompressor.com/ | ||
*Wrap code in | * Wrap content-specific code in jQuery plugin code: | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
(function($) { | |||
var methods = { | |||
<methodName>: function() { | |||
return this.each(function() { | |||
/* custom code goes here... */ | |||
} | }); | ||
} | |||
}; | |||
$.fn.<pluginName> = function( method ) { | |||
/* method calling logic */ | |||
if (methods[method]) { | |||
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | |||
} | |||
else if ( typeof method === 'object' || !method ) { | |||
return methods.init.apply(this, arguments); | |||
} | |||
else { | |||
$.error('Method ' + method + ' does not exist on jQuery.<pluginName>.'); | |||
} | |||
}; | |||
})(jQuery); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
*Use <code> | * Use <code>$.cms()</code> JQuery binding routines as much as possible | ||
* See also: [[Binding JQuery Handlers]] | |||
==Listings pages== | ==Listings pages== | ||
| Line 98: | Line 118: | ||
===Page framework=== | ===Page framework=== | ||
*Refactor header and footer includes to use the path <code>ADMIN_TEMPLATE_DIR."framework/"</code>. | * Refactor header and footer includes to use the path <code>ADMIN_TEMPLATE_DIR."framework/"</code>. | ||
*Use appropriate PHP include rollup for CSS/JavaScript resources for the page, e.g. | * Use appropriate PHP include rollup for CSS/JavaScript resources for the page, e.g. | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
include (ADMIN_TEMPLATE_DIR."framework/css/listings_css_and_scripts.php"); | include (ADMIN_TEMPLATE_DIR."framework/css/listings_css_and_scripts.php"); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
*Use JQuery initialization | * Use JQuery initialization | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
$(document).ready( | $(document).ready(function() { | ||
$('#listings-container').cms('bindListingsHandlers'); | |||
}); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
*See [[JQuery Initialization on Listings Pages]] | :* See [[Binding JQuery Handlers]] | ||
*See [[Sorting Listings|Configuration notes for sorting]]. | :* See [[JQuery Initialization on Listings Pages]] | ||
*Make sure to include a container for error messages on the page: | :* See [[Sorting Listings|Configuration notes for sorting]]. | ||
* Make sure to include a container for error messages on the page: | |||
<syntaxhighlight lang="html4strict"> | <syntaxhighlight lang="html4strict"> | ||
| Line 153: | Line 177: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* | * Use <code><nowiki><label></nowiki></code> tags around all form inputs. | ||
*Any textbox inputs that collect date values should be assigned the <code>“datepicker”</code> class. | *Any textbox inputs that collect date values should be assigned the <code>“datepicker”</code> class. | ||
<syntaxhighlight lang="php"> | |||
<td><label>name <input type="text" name="<?=$filters->name->param ?>" value="<?=$filters->name->value ?>" maxlength="50" /></label></td> | |||
</syntaxhighlight> | |||
*Submit button markup: | *Submit button markup: | ||
| Line 166: | Line 193: | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
if (!defined(" | if (!defined("[CONTENT-TYPE]_DETAILS_URI")) | ||
{ | { | ||
require_once (realpath(dirname(__FILE__).'/../../')."/_config/scripts.php"); | require_once (realpath(dirname(__FILE__).'/../../')."/_config/scripts.php"); | ||
| Line 263: | Line 290: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====Edit form==== | ====Edit form==== | ||
Form data to preserve in hidden inputs: | * Form data to preserve in hidden inputs: | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
<input type="hidden" name="<?=P_REFERER?>" value="<?=((isset($_REQUEST[P_REFERER]))?($_REQUEST[P_REFERER]):(""))?>" /> | <input type="hidden" name="<?=P_REFERER?>" value="<?=((isset($_REQUEST[P_REFERER]))?($_REQUEST[P_REFERER]):(""))?>" /> | ||
| Line 275: | Line 302: | ||
* [[Album_Image_Uploads#Album-based_content_using_a_gallery_image_as_a_thumbnail|Thumbnail upload controls]] | * [[Album_Image_Uploads#Album-based_content_using_a_gallery_image_as_a_thumbnail|Thumbnail upload controls]] | ||
Default form submission buttons and controls. Work off the contents of that include file for custom controls. | * Default form submission buttons and controls (including "next operation" radio options). Work off the contents of that include file for custom controls. | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
<? include (COMMON_TEMPLATE_DIR."forms/submit_container.php"); ?> | <? include (COMMON_TEMPLATE_DIR."forms/submit_container.php"); ?> | ||
| Line 295: | Line 322: | ||
==Details Pages== | ==Details Pages== | ||
Sample inline edit funcationality setup: | Sample inline edit funcationality setup: | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript" enclose="div"> | ||
$(document).ready(function(){ | $(document).ready(function(){ | ||
| Line 317: | Line 344: | ||
/* enables inline editing of keywords */ | /* enables inline editing of keywords */ | ||
$('.metadata').keywords('bindListingsHandlers'); | $('.metadata').keywords('bindListingsHandlers'); | ||
/* optional key navigation through records */ | |||
$(document).listings('bindKeyPageNavigation', { | |||
leftKeyURL: '<? if ($filters->prev_id > 0): print([CONTENT_SLUG]_DETAILS_URI."{$sParam}&id={$filters->prev_id}"); else: print([CONTENT_SLUG]_URI.$sParam); endif; ?>', | |||
rightKeyURL: '<? if ($filters->next_id > 0): print([CONTENT_SLUG]_DETAILS_URI."{$sParam}&id={$filters->next_id}"); else: print([CONTENT_SLUG]_URI.$sParam); endif; ?>', | |||
upKeyURL: '<?=[CONTENT_SLUG]_URI.$sParam ?>' | |||
}); | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Latest revision as of 17:28, 13 December 2012
Configuration[edit]
Update content settings in site sections CMS[edit]
- AJAX scripts
- Listings:
/_hostmgr/_ajax/utils/listings.phpor/_hostmgr/[CONTENT]/_ajax/listings.php - Delete:
/_hostmgr/_ajax/utils/delete_record.php - Update cache:
/_hostmgr/_ajax/utils/update_cache.php - Resort:
/_hostmgr/_ajax/utils/resort.php
- Listings:
- ID parameter
- Sortable flag
- Cache Content flag
Rename existing directories in VCS[edit]
common>_configcommon/*.js>_scripts/*.jsinline>_ajaxforms>_templates/formscontent>_templates/content
Refactor PHP content class[edit]
- Refactor include directives
- (Optional) add Netbeans-friendly class documentation
- Wrap code within functions in
try { /*...*/ } catch (Exception $ex) { /*...*/ } - Use
db_content_classas base class for all classes that represent records in the database.
Refactor PHP content filtering class[edit]
- Refactor include directives
- (Optional) add Netbeans-friendly class documentation
- Refer to a class that’s been refactored for logic updates within the class’s routines.
- Use
filter_collection_classas base class for any class that represents records in the database. - Add
$site_sectionproperty to any class that handles listings and pagination.
TODO: Consider making this a property offilter_collection_class. - Add
$section_operationsproperty to any class that handles listings and pagination.
TODO: Consider making this a property offilter_collection_class.
Add content handlers to PHP cache and resort classes[edit]
- Add include directives for PHP content and content filtering classes to cache_class
- Add case for the content type in class routines as necessary
cache_class::update_content()cache_class::set_initial_properties()cache_class::update_keywords()cache_class::set_filters()cache_class::set_content()cache_class::load_json_content()cache_class::refresh_content_after_edit()cache_class::refresh_content_after_image_edit()resort_class::retrieve_section_properties()
Refactor config files[edit]
_config/core_includes.php- fix paths to include files.
- Refactor
_config/scripts.php- add definition for
SECTION_BASE_URI *_SCRIPT>*_URIADMIN_HTTP_ROOT_URI."section_name/">SECTION_BASE_URI."
- add definition for
Local AJAX scripts[edit]
- Refactor include directives
- (Optional) refactor to use
ajax_page_class - Add any necessary scripts
listings.php
Local JavaScript libraries[edit]
- Minify existing libraries
- Created “source” version of existing libraries:
lib.js>lib-source.js - Compress existing libraries: http://javascriptcompressor.com/
- Created “source” version of existing libraries:
- Wrap content-specific code in jQuery plugin code:
(function($) {
var methods = {
<methodName>: function() {
return this.each(function() {
/* custom code goes here... */
});
}
};
$.fn.<pluginName> = function( method ) {
/* method calling logic */
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if ( typeof method === 'object' || !method ) {
return methods.init.apply(this, arguments);
}
else {
$.error('Method ' + method + ' does not exist on jQuery.<pluginName>.');
}
};
})(jQuery);
- Use
$.cms()JQuery binding routines as much as possible - See also: Binding JQuery Handlers
Listings pages[edit]
Page setup & initialization[edit]
- (Optional) Update comments to use Netbeans editor folds:
//<editor-fold> - Refactor include directives
- Refactor local CMS page URI definitions (
*_SCRIPT>*_URI) - Add
$breadcrumbs,$sTitleas global variables in the page’sinitialize()function. - When calling
$filters->format_query_string(), make sure not to append any values forP_FILTER. - Remove calls to
urlencode()when formatting URLs for header links. - Use shared AJAX script for any “update cache” links.
- Configure breadcrumbs.
Page framework[edit]
- Refactor header and footer includes to use the path
ADMIN_TEMPLATE_DIR."framework/". - Use appropriate PHP include rollup for CSS/JavaScript resources for the page, e.g.
include (ADMIN_TEMPLATE_DIR."framework/css/listings_css_and_scripts.php");
- Use JQuery initialization
$(document).ready(function() {
$('#listings-container').cms('bindListingsHandlers');
});
- Make sure to include a container for error messages on the page:
<div id="error-container" class="error" style="display:none;"></div>
- Wrap listings in a container that will allow JQuery script to locate them:
<div id="listings-container" class="listings">
<? include (SECTION_BASE_DIR."_templates/content/[CONTENT-TYPE]_listings.php"); ?>
</div>
- Remove any includes for popup containers.
Filters form[edit]
- Update any lib routines to use the analogous routine from a utility class. E.g.
db_utils_class::display_cached_options() - Form container has id
“listings-filters”and class“listings-filters ui-corner-all”. Make sure to include JQuery UI stylesheet and that the local stylesheet contains the relevant definitions.
<div id="listings-filters" class="listings-filters ui-corner-all">
- Form element has method “get”, id “filters_form”, and class “filters”.
<form action="<?=SECTION_CMS_URI ?>" method="get" id="filters_form">
- Store “next” filter value in form.
<input type="hidden" name="<?=$filters->next->param ?>" value="<?=$filters->next->value ?>" />
- Table element within form does not have any attributes.
<table>
- Use
<label>tags around all form inputs. - Any textbox inputs that collect date values should be assigned the
“datepicker”class.
<td><label>name <input type="text" name="<?=$filters->name->param ?>" value="<?=$filters->name->value ?>" maxlength="50" /></label></td>
- Submit button markup:
<input type="submit" class="filter-btn ui-corner-all" name="<?=P_FILTER ?>" value="filter" />
Listings content include file[edit]
- (Optional) Add include directive for the section’s scripts config file for the benefit of the cache_class routines. Test if one of the script definitions is defined. If not, include the scripts config file.
if (!defined("[CONTENT-TYPE]_DETAILS_URI"))
{
require_once (realpath(dirname(__FILE__).'/../../')."/_config/scripts.php");
}
- Add try/catch for retrieving listings.
- Remove include directives for any stand-alone routines that render pagination links.
- Use shared include file to render pagination links.
include (COMMON_TEMPLATE_DIR."framework/navigation/listings_page_links.php");
- Add attributes to table elements to support pagination and sorting.
- Remove “slot” column from listings.
- Use
listandlist-altCSS classes for alternating rows to support onHover behaviors. - Use shared templates for inline edit elements:
<? include (COMMON_TEMPLATE_DIR."forms/ajax/status_cell.php"); ?>
Edit Pages[edit]
Page setup & initialization[edit]
- The points under the listings pages setup & initialization apply here also.
- Refactor stand-alone routines such as
parse_numeric_input()to use analogous routines in shared utility classes, e.gvalidation_class::parse_numeric_input(). - Set exception handler for the page that will load the page framework with the caught error displayed at the top:
set_exception_handler("exception_handler");
and
function exception_handler($ex)
{
global $nav_menu, $breadcrumbs, $sTitle, $sParam, $input, $filters;
$input->error_string = $ex->getMessage();
include (SECTION_BASE_DIR."_templates/edit_[CONTENT-TYPE]_page.php");
}
Page framework[edit]
- Points under listings pages framework that don’t refer to the listings apply here also.
- Page framework is located in
include (SECTION_BASE_DIR."_templates/edit_[CONTENT-TYPE]_page.php");
Gallery listings[edit]
- If editing an existing record, load gallery listings with
$(document).ready(function() {
<? if ($input->id->value>0): ?>
$('#pages-<?=$input->id->value?>').galleries('retrieveGallery', function() {
$('#pages-<?=$input->id->value?>').galleries('bindImageOverlayHandlers');
});
<? endif; ?>
});
$.galleries('retrieveGallery')in turn calls$.galleries('bindGalleryHandlers'). All AJAX button handlers should be fully active after the gallery listings are rendered.- The gallery images still need to be retrieved in PHP when the parent record is read even though they are displayed with this AJAX call. TODO: fix this so that the gallery properties are retrieved even when the gallery images are not retrieved.
$input->read(true); /* <<< true = retrieve gallery images */
TinyMCE WYSIWYG editors[edit]
- JavaScript includes
<script type="text/javascript" src="/scripts/tiny_mce/tiny_mce.js"></script> <script type="text/javascript" src="/scripts/tinymce_config.js"></script>
- The first one, the TinyMCE library, is in the common directories. The second one is local, and allows local configuration of the WYSIWYG editors.
- Assign a textbox
class="mce-editor"to have a TinyMCE WYSIWYG editor attached to it.
class content_type extends db_content_class
{
function __construct()
{
parent::__construct();
$this->description = new string_textarea_class("Description", self::DESCR_PARAM, false, "", 2000);
$this->description->class = "mce-editor";
}
}
Edit form[edit]
- Form data to preserve in hidden inputs:
<input type="hidden" name="<?=P_REFERER?>" value="<?=((isset($_REQUEST[P_REFERER]))?($_REQUEST[P_REFERER]):(""))?>" />
<input type="hidden" name="MAX_FILE_SIZE" value="10240000" />
<input type="hidden" name="<?=P_ID?>" value="<?=$input->id->value?>" />
<input type="hidden" name="<?=$input->id->param?>" value="<?=$input->id->value?>" />
<input type="hidden" name="<?=$input->slot->param ?>" value="<?=$input->slot->value ?>" />
<? $filters->preserve_in_form(); ?>
- Default form submission buttons and controls (including "next operation" radio options). Work off the contents of that include file for custom controls.
<? include (COMMON_TEMPLATE_DIR."forms/submit_container.php"); ?>
Main page logic[edit]
- Remove checks on
if($input->error()). Let the exception handler catch and handle these errors. - Put status messages in session variables:
$_SESSION[P_MESSAGE] = $sStatus;
- For image and thumbnail uploads, and album-based content types displaying galleries:
- See also Neighbor Links Navigation
Details Pages[edit]
Sample inline edit funcationality setup:
$(document).ready(function(){
/* with album-based content, this loads the gallery of images on the page */
$('#pages-<?=$input->id->value?>').galleries('retrieveGallery', function() {
/* callback code executed after the gallery is fully loaded into the DOM */
$('#pages-<?=$input->id->value?>')
/* with a gallery of full-sized images this would load edit & delete buttons after clicking the images */
.galleries('bindImageOverlayHandlers')
/* with a listings-style of presentation this would enable inline editing of keywords within the gallery */
.keywords('bindListingsHandlers');
});
/* adds edit and delete buttons to thumbnail image */
/* this works for both album-based thumbnails and stand-alone images linked to the parent record */
$('.image-upload-container').galleries('bindImageOverlayHandlers');
/* enables inline editing of keywords */
$('.metadata').keywords('bindListingsHandlers');
/* optional key navigation through records */
$(document).listings('bindKeyPageNavigation', {
leftKeyURL: '<? if ($filters->prev_id > 0): print([CONTENT_SLUG]_DETAILS_URI."{$sParam}&id={$filters->prev_id}"); else: print([CONTENT_SLUG]_URI.$sParam); endif; ?>',
rightKeyURL: '<? if ($filters->next_id > 0): print([CONTENT_SLUG]_DETAILS_URI."{$sParam}&id={$filters->next_id}"); else: print([CONTENT_SLUG]_URI.$sParam); endif; ?>',
upKeyURL: '<?=[CONTENT_SLUG]_URI.$sParam ?>'
});
}
- For image and thumbnail uploads, and album-based content types displaying galleries:
- See also Neighbor Links Navigation