diff --git a/README.md b/README.md index 85a4648..dc0dca8 100755 --- a/README.md +++ b/README.md @@ -3,17 +3,57 @@ SilverStripe Inline Help Module Maintainer Contacts ------------------- -* Andrew Short () +* Tom Brewer-Vinga () Requirements ------------ -* SilverStripe 2.4+ +* SilverStripe 3.2+ Documentation ------------- +Changelog +------------- + +**2.0** + + - Add Bootstrap Popover support + - Remove JQueryUI support (will be re-implemented later) + - Split InlineHelpTopic into core dataobject and extensions to support different javascript libraries + +**1.0** + +- Updated to SilverStripe 3.2 + - Earlier versions of SilverStripe 3 have not been tested + +Known Bugs +---------- + +- The displayed fields in the admin section under the tab "Attach To" display incorrectly with the selected radio button when the item is dynamically loaded + Installation Instructions ------------------------- 1. Place this directory in the root of your SilverStripe installation. -2. Visit yoursite.com/dev/build to rebuild the database. \ No newline at end of file + +2. If cloned or using the zip file, change the directory to just `inlinehelp` + +3. Add the following lines of code to your Page init function +``` +if($this->dataRecord) { + $this->dataRecord->extend('onPageInit', $this); +} else { + singleton('SiteTree')->extend('onPageInit', $this); +} +``` +4. Add the below snippet your projects yml configuration to enable the bootstrap popover boxes +``` +SiteTree: + extensions: + - InlineHelpExtension +InlineHelpTopic: + extensions: + - InlineHelpTopicBootstrap +``` + +4. Visit yoursite.com/dev/build to rebuild the database. diff --git a/_config.php b/_config.php index 1a18cd5..e9af8b8 100755 --- a/_config.php +++ b/_config.php @@ -3,22 +3,22 @@ * @package silverstripe-inlinehelp */ -Object::add_extension('SiteTree', 'InlineHelpExtension'); +define('INLINEHELP_DIR', basename(dirname(__FILE__))); /** * Set up a simplified HTML editor config for use in help text. */ -HtmlEditorConfig::get('simple')->setOptions(array( +HtmlEditorConfig::get('helpsimple')->setOptions(array( 'friendly_name' => 'Simple', 'language' => i18n::get_tinymce_lang(), 'document_base_url' => Director::absoluteBaseURL(), 'mode' => 'specific_textareas', 'valid_elements' => '*[*]' )); -HtmlEditorConfig::get('simple')->setButtonsForLine(1, array( +HtmlEditorConfig::get('helpsimple')->setButtonsForLine(1, array( 'bold', 'italic', 'underline', 'strikethrough', 'separator', 'undo', 'redo', 'separator', 'formatselect', 'cleanup', 'separator', 'bullist', 'numlist' )); -HtmlEditorConfig::get('simple')->setButtonsForLine(2); -HtmlEditorConfig::get('simple')->setButtonsForLine(3); \ No newline at end of file +HtmlEditorConfig::get('helpsimple')->setButtonsForLine(2); +HtmlEditorConfig::get('helpsimple')->setButtonsForLine(3); \ No newline at end of file diff --git a/_config/_extensions.yml b/_config/_extensions.yml new file mode 100644 index 0000000..e69de29 diff --git a/code/InlineHelpAdmin.php b/code/InlineHelpAdmin.php index ff713a3..106ab76 100755 --- a/code/InlineHelpAdmin.php +++ b/code/InlineHelpAdmin.php @@ -16,7 +16,8 @@ class InlineHelpAdmin extends ModelAdmin { public function init() { parent::init(); - HtmlEditorConfig::set_active('simple'); + // Commented out due to a bug with Editor init + //HtmlEditorConfig::set_active('helpsimple'); } } \ No newline at end of file diff --git a/code/InlineHelpExtension.php b/code/InlineHelpExtension.php index 86de1db..5865e3e 100755 --- a/code/InlineHelpExtension.php +++ b/code/InlineHelpExtension.php @@ -4,25 +4,23 @@ * * @package silverstripe-inlinehelp */ -class InlineHelpExtension extends DataObjectDecorator { +class InlineHelpExtension extends DataExtension { - /** - * @return array - */ - public function extraStatics() { - return array('belongs_many_many' => array( - 'HelpTopics' => 'InlineHelpTopic' - )); - } + private static $belongs_many_many = array( + 'HelpTopics' => 'InlineHelpTopic' + ); /** * Includes the required JS libraries and inline help definitions. */ - public function contentcontrollerInit() { - $template = 'InlineHelp'; - $include = $this->owner->renderWith($template); + public function onPageInit() { + if($this->owner->HelpItems) { + $include = $this->owner->renderWith('InlineHelp'); + if ($include) Requirements::customScript($include); + Requirements::javascript(INLINEHELP_DIR . '/javascript/inlinehelp.bootstrap.popover.js'); + Requirements::css(INLINEHELP_DIR . '/css/inlinehelpbootstrap.css'); + } - if ($include) Requirements::customScript($include); } /** @@ -31,12 +29,10 @@ public function contentcontrollerInit() { * @return InlineHelpTopic[] */ public function getHelpItems() { - $items = new DataObjectSet(); + $items = new ArrayList(); - $items->merge(DataObject::get('InlineHelpTopic', - '"AttachType" = \'All\'')); - $items->merge(DataObject::get( - 'InlineHelpTopic', + $items->merge(InlineHelpTopic::get()->where('"AttachType" = \'All\'')); + $items->merge(InlineHelpTopic::get()->where( sprintf( '"AttachType" = \'Type\' AND "AttachPageType" = \'%s\'', $this->owner->class @@ -48,7 +44,8 @@ public function getHelpItems() { array_shift($stack); if ($stack) { - $items->merge(DataObject::get('InlineHelpTopic', sprintf( + $items->merge(InlineHelpTopic::get()->where( + sprintf( '"AttachType" = \'Children\' AND "ParentFilterID" IN(%s)', implode(', ', array_map(create_function('$self', 'return $self->ID;'), diff --git a/code/InlineHelpTopic.php b/code/InlineHelpTopic.php index e573328..864daef 100755 --- a/code/InlineHelpTopic.php +++ b/code/InlineHelpTopic.php @@ -7,6 +7,13 @@ */ class InlineHelpTopic extends DataObject { + private static $attachment_method_map = array( + 'appendTo' => 'Append to', + 'prependTo' => 'Prepend to', + 'insertBefore' => 'Insert before', + 'insertAfter' => 'Insert after' + ); + public static $db = array( 'Title' => 'Varchar(100)', 'DisplayType' => 'Enum("Tooltip, Link", "Tooltip")', @@ -14,16 +21,7 @@ class InlineHelpTopic extends DataObject { 'Link' => 'Varchar(100)', 'AttachType' => 'Enum("All, Pages, Children, Type", "Pages")', 'AttachPageType' => 'Varchar(100)', - 'DOMPattern' => 'Varchar(100)', - 'ShowTooltip' => 'Enum("Hover, Click", "Hover")', - 'TooltipWidth' => 'Varchar(6)', - 'TooltipHeight' => 'Varchar(6)', - 'IconHTML' => 'HTMLVarchar(255)', - 'IconMy' => 'Varchar(15)', - 'IconAt' => 'Varchar(15)', - 'IconOffset' => 'Varchar(10)', - 'TooltipMy' => 'Varchar(15)', - 'TooltipAt' => 'Varchar(15)' + 'DOMPattern' => 'Varchar(100)' ); public static $has_one = array( @@ -65,7 +63,7 @@ public function getAttachedTo() { case 'All': return 'All pages'; case 'Pages': - return 'Specific pages: ' . implode(', ', $this->Pages()->map()); + return 'Specific pages: ' . implode(', ', $this->Pages()->toArray()); case 'Children': return 'Children of ' . $this->ParentFilter()->Title; case 'Type': @@ -80,7 +78,7 @@ public function getCMSFields() { Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); Requirements::javascript('inlinehelp/javascript/InlineHelpAdmin.js'); - return new FieldSet(new TabSet('Root', + $fields = new FieldList(new TabSet('Root', new Tab('Main', new HeaderField('HelpHeader', 'Help Topic'), new TextField('Title', 'Title'), @@ -88,7 +86,7 @@ public function getCMSFields() { 'Tooltip' => 'Display help text and/or link in tooltip', 'Link' => 'Click the icon to go to the help link' )), - new HtmlEditorField('Text', 'Short help text', 8), + new HtmlEditorField('Text', 'Short help text'), new TextField('Link', 'Help link') ), new Tab('Subject', @@ -97,7 +95,8 @@ public function getCMSFields() { new LiteralField('DOMPatternNote', '

This is a jQuery (CSS) selector which specifies which elements to attach this help topic to. The same topic can be attached to multiple elements. -

') +

'), + new DropdownField('DOMMethod', 'DOM attachment method', self::$attachment_method_map) ), new Tab('AttachTo', new HeaderField('AttachToHeader', 'Attach Help To'), @@ -112,41 +111,12 @@ public function getCMSFields() { new DropdownField('AttachPageType', 'Page type', ArrayLib::valuekey( ClassInfo::subclassesFor('Page') )) - ), - new Tab('Advanced', - new HeaderField('AdvancedHeader', 'Advanced Inline Help Options'), - new DropdownField('ShowTooltip', 'Show tooltip on', array( - 'Hover' => 'On mouse hover', - 'Click' => 'On mouse click' - )), - new TextField('IconHTML', 'Icon HTML code'), - new FieldGroup('Help icon position (relative to subject)', - new TextField('IconMy', 'my'), - new TextField('IconAt', 'at') - ), - new FieldGroup('Help icon offset (relative to position)', - new TextField('IconOffset', ''), - new LiteralField('IconOffsetNote', - 'format "horizontal vertical" (e.g. "15 -5")') - ), - new FieldGroup('Tooltip position (relative to icon)', - new TextField('TooltipMy', 'my'), - new TextField('TooltipAt', 'at') - ), - new LiteralField('HelpPositionNote', '

These allow you to - specify the position of the elements relative to each other. - Each position is in the format "horizontal vertical", where - horizontal can be one of left, center or right (default - center), and vertical can be top, center or bottom (default - center)

'), - new FieldGroup('Tooltip size', - new TextField('TooltipWidth', ''), - new LiteralField('SizeSeparator', 'x'), - new TextField('TooltipHeight', ''), - new LiteralField('DefaultSizeNote', '(default: 300 x "auto")') - ) ) )); + + $this->extend('updateCMSFields', $fields); + + return $fields; } } \ No newline at end of file diff --git a/code/InlineHelpTopicBootstrap.php b/code/InlineHelpTopicBootstrap.php new file mode 100644 index 0000000..5c9ca03 --- /dev/null +++ b/code/InlineHelpTopicBootstrap.php @@ -0,0 +1,38 @@ + + */ +class InlineHelpTopicBootstrap extends DataExtension { + + private static $db = array( + 'container' => 'Varchar', + 'html' => 'Boolean(0)', + 'placement' => 'Enum("top, right, bottom, left", "right")', + 'trigger' => 'Enum("hover focus, click", "click")' + /* TODO(Steve) need a way to set custom templates for pop ups */ + //'template' => 'Varchar', + ); + + public function updateCMSFields(FieldList $fields) { + $fields->addFieldToTab('Root', + new Tab('Advanced', + new HeaderField('AdvancedHeader', 'Advanced Inline Help Options'), + new DropdownField('trigger', 'Show tooltip on', array( + 'click' => 'On mouse click', + 'hover focus' => 'On mouse hover' + )), + new LiteralField('HelpPositionNote', '

Set the default pop over placement. For example, if placement + is "left", the popover will display to the left when possible, otherwise it will display right.

'), + new DropdownField('placement', 'Place tooltip to the', array( + 'right' => 'Right', + 'left' => 'Left', + 'top' => 'Top', + 'bottom' => 'Bottom' + )) + ) + ); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..642757e --- /dev/null +++ b/composer.json @@ -0,0 +1,23 @@ +{ + "name": "silverstripe-australia/inlinehelp", + "description": "", + "type": "silverstripe-module", + "keywords": ["silverstripe", "inline", "help"], + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Tom Brewer-Vinga", + "email": "tom@silverstripe.com.au" + } + ], + "require": + { + "silverstripe/cms": "3.*", + "silverstripe/framework": "3.*", + "composer/installers": "*" + }, + "extra": { + "installer-name": "inlinehelp" + }, + "minimum-stability": "dev" +} diff --git a/css/inlinehelpbootstrap.css b/css/inlinehelpbootstrap.css new file mode 100644 index 0000000..560a2de --- /dev/null +++ b/css/inlinehelpbootstrap.css @@ -0,0 +1,11 @@ +.btn-inlinehelp { + padding: 0.2em 0.3em 0; + border: none; + margin: 0.3em; + border-radius: 50%; +} + +.btn-inlinehelp .glyphicon { + color: #0a7cb9; + font-size: 100%; +} \ No newline at end of file diff --git a/css/ss.inlinehelp.css b/css/ss.inlinehelp.css deleted file mode 100755 index fc80cb1..0000000 --- a/css/ss.inlinehelp.css +++ /dev/null @@ -1,49 +0,0 @@ -.ss-inlinehelp-icon, .ss-inlinehelp-tooltip { - position: absolute; - top: 0; -} - -.ss-inlinehelp-icon { - z-index: 9998; -} - -.ss-inlinehelp-tooltip { - z-index: 9999; - overflow: hidden; -} - -.ss-inlinehelp-tooltip-title, .ss-inlinehelp-tooltip-link { - padding: 2px 4px; - border-left: none; - border-right: none; -} - -.ss-inlinehelp-tooltip-title { - border-top: none; - position: absolute; - right: 0; - left: 0; - top: 0; - text-align: center; - width: 100%; -} - -.ss-inlinehelp-tooltip-content { - padding: 4px; - left: 0; - right: 0; - position: absolute; -} - -.ss-inlinehelp-tooltip-link { - position: absolute; - bottom: 0; - left: 0; - right: 0; - border-bottom: none; - width: 100%; -} - -.ss-inlinehelp-click, .ss-inlinehelp-link { - cursor: pointer; -} \ No newline at end of file diff --git a/javascript/InlineHelpAdmin.js b/javascript/InlineHelpAdmin.js index c5a5ef9..0a6e962 100755 --- a/javascript/InlineHelpAdmin.js +++ b/javascript/InlineHelpAdmin.js @@ -1,53 +1,45 @@ ;(function($) { - Behaviour.register({ - '#AttachType': { - initialize: function() { - $(this).find(':checked').change(); - } - }, - '#DisplayType': { - initialize: function() { - $(this).find(':checked').change(); - } - } + $(document).on('ready', function() { + $('#AttachType').find(':checked').change(); + $('#DisplayType').find(':checked').change(); }); - $('#AttachType :radio').live('change', function() { + $('#AttachType :radio').on('change', function() { switch ($(this).val()) { case 'All': - $('#ParentFilterID').hide(); - $('#Pages').hide(); - $('#AttachPageType').hide(); + $('#Form_ItemEditForm_ParentFilterID_Holder').hide(); + $('#Form_ItemEditForm_Pages_Holder').hide(); + $('#Form_ItemEditForm_AttachPageType_Holder').hide(); break; case 'Pages': - $('#ParentFilterID').hide(); - $('#Pages').show(); - $('#AttachPageType').hide(); + $('#Form_ItemEditForm_ParentFilterID_Holder').hide(); + $('#Form_ItemEditForm_Pages_Holder').show(); + $('#Form_ItemEditForm_AttachPageType_Holder').hide(); break; case 'Children': - $('#ParentFilterID').show(); - $('#Pages').hide(); - $('#AttachPageType').hide(); + $('#Form_ItemEditForm_ParentFilterID_Holder').show(); + $('#Form_ItemEditForm_Pages_Holder').hide(); + $('#Form_ItemEditForm_AttachPageType_Holder').hide(); break; case 'Type': - $('#ParentFilterID').hide(); - $('#Pages').hide(); - $('#AttachPageType').show(); + $('#Form_ItemEditForm_ParentFilterID_Holder').hide(); + $('#Form_ItemEditForm_Pages_Holder').hide(); + $('#Form_ItemEditForm_AttachPageType_Holder').show(); break; } }); - $('#DisplayType :radio').live('change', function() { + $('#DisplayType :radio').on('change', function() { switch ($(this).val()) { case 'Tooltip': - $('#Text.htmleditor').show(); + $('#Form_ItemEditForm_Text.htmleditor').show(); break; case 'Link': - $('#Text.htmleditor').hide(); + $('#Form_ItemEditForm_Text.htmleditor').hide(); break; } }); diff --git a/javascript/inlinehelp.bootstrap.popover.js b/javascript/inlinehelp.bootstrap.popover.js new file mode 100644 index 0000000..4cdc17f --- /dev/null +++ b/javascript/inlinehelp.bootstrap.popover.js @@ -0,0 +1,14 @@ +$(document).ready(function() { + if(typeof SS_InlineHelpItems !== 'undefined') { + $.each(SS_InlineHelpItems, function(element,options) { + options.html = true; + var pop = $('') + .attr('type', 'button') + .html('') + .addClass('btn btn-default btn-inlinehelp'); + options.container = $(element).parent(); + pop.popover(options); + pop.appendTo($(element)); + }); + } +}); \ No newline at end of file diff --git a/javascript/ss.inlinehelp.js b/javascript/ss.inlinehelp.js deleted file mode 100755 index 31bf145..0000000 --- a/javascript/ss.inlinehelp.js +++ /dev/null @@ -1,165 +0,0 @@ -;(function($) { - /** - * Embeds a configurable inline help icon with a link or tooltip popup next - * to an element. - */ - $.widget('ss.inlineHelp', { - options: { - type: 'tooltip', - title: 'Help', - icon: '', - iconPosition: { - my: 'left top', - at: 'right top' - }, - showOn: 'hover', - text: '', - link: false, - linkFormat: 'More information', - tooltipClass: '', - tooltipPosition: { - my: 'left top', - at: 'right top' - }, - tooltipSize: { - width: 300, - height: 'auto' - }, - showOn: 'hover', - tooltipDelay: 200 - }, - _init: function() { - var widget = this; - - var updatePosition = function () { - widget.icon.position($.extend(widget.options.iconPosition, { - of: widget.element - })); - } - - $(window).scroll(updatePosition); - var updateInterval = setInterval(updatePosition, 1000); - - if (this.options.type == 'link') { - this.link = $('') - .addClass('ss-inlinehelp-link') - .attr('href', this.options.link) - .attr('title', this.options.title) - .html(this.options.icon); - - this.icon = $('
') - .addClass('ss-inlinehelp-icon ui-state-default ui-corner-all') - .addClass('ss-inlinehelp-click') - .html(this.link) - .appendTo(document.body) - .position($.extend(this.options.iconPosition, { - of: this.element - })); - - return; - } - - this.icon = $('
') - .addClass('ss-inlinehelp-icon ui-state-default ui-corner-all') - .html(this.options.icon) - .appendTo(document.body) - .position($.extend(this.options.iconPosition, { - of: this.element - })); - - this.tooltip = $('
') - .addClass('ss-inlinehelp-tooltip ui-widget ui-widget-content ui-corner-all') - .addClass(this.options.tooltipClass) - .appendTo(document.body) - .hide(); - - this.tooltipHeader = $('
') - .addClass('ss-inlinehelp-tooltip-title ui-widget-header ui-corner-top') - .html(this.options.title) - .appendTo(this.tooltip); - - this.tooltipContent = $('
') - .addClass('ss-inlinehelp-tooltip-content') - .html(this.options.text) - .appendTo(this.tooltip); - - if (this.options.link) { - var linkHTML = this.options.linkFormat - .replace('$Link', this.options.link); - - this.tooltipLink = $('
') - .addClass('ss-inlinehelp-tooltip-link ui-widget-header ui-corner-bottom') - .html(linkHTML) - .appendTo(this.tooltip); - } else { - this.tooltipContent.addClass('ui-corner-bottom'); - } - - if (this.options.showOn == 'click') { - this.icon - .addClass('ss-inlinehelp-click') - .click(function() { - widget.openTooltip(); - widget.tooltip.addClass('ss-inlinehelp-hideonclick'); - - return false; - }); - - $(document).click(function() { - $('.ss-inlinehelp-hideonclick').hide(); - }); - } else { - $([this.icon, this.tooltip]).each(function(i, el) { - el.hover(function() { - widget.clearTimeout(); - widget.openTooltip(); - }, function() { - widget.startTimeout(); - }); - }); - } - }, - openTooltip: function() { - if (this.tooltip.is(':hidden')) { - this.tooltip - .show() - .width(this.options.tooltipSize.width) - .height(this.options.tooltipSize.height) - .position($.extend(this.options.tooltipPosition, { - of: this.icon - })); - - this.tooltipContent - .css('top', this.tooltipHeader.outerHeight()); - - if (this.options.tooltipSize.height != 'auto') { - this.tooltipContent.css({ - bottom: 0, - overflow: 'auto' - }); - } else { - var height = this.tooltipHeader.height() + this.tooltipContent.outerHeight(); - if (this.tooltipLink) height += this.tooltipLink.height(); - this.tooltip.height(height + 5); - } - - if (this.tooltipLink) { - this.tooltipContent - .css('bottom', this.tooltipLink.outerHeight()); - } - } - }, - closeTooltip: function() { - this.tooltip.hide(); - }, - startTimeout: function() { - var self = this; - this.timeout = setTimeout( - function() { self.closeTooltip(); }, this.options.tooltipDelay - ); - }, - clearTimeout: function() { - if (this.timeout) clearTimeout(this.timeout); - } - }) -})(jQuery); \ No newline at end of file diff --git a/templates/InlineHelp.ss b/templates/InlineHelp.ss index 0a3100a..0789750 100755 --- a/templates/InlineHelp.ss +++ b/templates/InlineHelp.ss @@ -1,41 +1,17 @@ <% if HelpItems %> - <% require css(sapphire/thirdparty/jquery-ui-themes/base/jquery.ui.all.css) %> - <% require css(inlinehelp/css/ss.inlinehelp.css) %> - - <% require javascript(sapphire/thirdparty/jquery/jquery.js) %> - <% require javascript(sapphire/thirdparty/jquery-ui/jquery-ui-1.8rc3.custom.js) %> - <% require javascript(sapphire/thirdparty/jquery-livequery/jquery.livequery.js) %> - <% require javascript(inlinehelp/javascript/ss.inlinehelp.js) %> - -(function($) { - <% control HelpItems %> - $('$DOMPattern').livequery(function() { $(this).inlineHelp({ - <% if IconHTML %>icon: '$IconHTML.JS',<% end_if %> - <% if IconMy && IconAt %> - iconPosition: { - <% if IconOffset %>offset: '$IconOffset.JS',<% end_if %> - my: '$IconMy.JS', - at: '$IconAt.JS' - }, - <% end_if %> - <% if TooltipMy && TooltipAt %> - tooltipPosition: { - my: '$TooltipMy.JS', - at: '$TooltipAt.JS' - }, - <% end_if %> - <% if TooltipWidth && TooltipHeight %> - tooltipSize: { - width: $TooltipWidth.JS, - height: $TooltipHeight.JS - }, - <% end_if %> +var SS_InlineHelpItems = { + <% loop $HelpItems %> + '$DOMPattern' : { type: '$DisplayType.Lower.JS', title: '$Title.JS', - text: '$Text.JS', + content: '$Text.JS', link: '$Link.JS', - showOn: '$ShowTooltip.Lower.JS' - }); }); - <% end_control %> -})(jQuery); + trigger: '$trigger', + <% if $container %>container: '$container',<% end_if %> + <% if $html %>html: '$html',<% end_if %> + placement: 'auto $placement', + container: 'body' + }<% if not $Last %>,<% end_if %> + <% end_loop %> +} <% end_if %> \ No newline at end of file