Expandable Ticker
A Customizable Content Ticker for your Ghost site, either site-wide or just on certain posts or pages...
Header Code Injection...
<style>
.expandticker{
border:1px solid black;
padding:7px;
background:lightyellow;
width: 200px;
height:130px;
overflow-y:auto; /*set DIV to scroll if content exceeds ticker height*/
position: relative;
}
.expandcontent{
display:none;
}
ul.dropdownlist{
font: normal 13px Verdana;
margin: 0;
padding: 0;
position: absolute;
left: 0;
top: 0;
z-index: 100;
list-style-type: none;
background: white;
border: 1px solid #ca431a;
padding: 3px;
}
ul.dropdownlist li a{
display: block;
background: #ffdb8d;
color: black;
text-decoration: none;
padding: 3px 5px 3px 3px;
}
ul.dropdownlist li a:hover{
background: #ffbf6d;
color: black;
}
ul.dropdownlist li.selected a{
background: #ca431a;
color: white;
}
</style>
Footer Code Injection...
<script>
/* Expandable Drop Down Ticker
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code
* Last Edited: Jan 25th, 2010
*/
var expandticker={
buttonhtml: '<img src="https://ghost-o-matic.com/content/images/2023/01/show-all.webp" style="width:70px; height:27px; cursor:pointer" />', //HTML of "expand" button
buttonoffset: [5, -10], //offset of button from lower left edge of ticker
//No need to edit beyond here
dsetting: {snippetlength:30, manual:false, timers: {rotatepause:3000, fxduration:300}},
effectfuncts: ['fadeIn', 'slideDown'],
fetchajaxcontent:function($, s){
window.status+='x'
clearTimeout(s.playtimer) //clear timers and remove $button, $menu if fetchajaxcontent() is being called more than once
clearTimeout(s.pausetimer)
clearTimeout(s.refreshtimer)
if (s.$button){
s.$button.remove()
s.$menu.remove()
}
s.$ticker.html("(Re)Fetching Ticker Contents...")
$.ajax({
url: s.remotecontent[0],
dataType: 'html',
error:function(ajaxrequest){
s.$ticker.html('Error fetching content.<br />Server Response: '+ajaxrequest.responseText)
},
success:function(content){
s.$ticker.html(content)
expandticker.setup($, s)
if (s.remotecontent[1]>5000) //5 secs minimum time allowed between updates
s.refreshtimer=setTimeout(function(){expandticker.fetchajaxcontent($, s)}, s.remotecontent[1])
else if (s.remotecontent[1]>0) //if value is NOT 0 (0=never refetch)
alert("Please Enter a value larger than 5 (sec) for the time between Ajax updates")
}
})
},
getmsgtitles:function(s){
var titlearray=[]
for (var i=0; i<s.msglength; i++){
var title=s.$contents.eq(i).attr('title') || s.$contents.eq(i).text().substring(0, s.snippetlength)+' ...' //extract snippet of message
titlearray.push(title)
}
return titlearray
},
adddropmenu:function($, s){
var titles=this.getmsgtitles(s)
var $lis=$([])
var $menu=$('<ul class="dropdownlist"></ul>')
for (var i=0; i<s.msglength; i++){ //construct a new LI element for each ticker message title
$lis=$lis.add($('<li/>').html((i+1)+". "+titles[i]).wrapInner('<a href="#message'+(i+1)+'" data-pos="'+i+'"></a>'))
}
$menu.append($lis).hide().unbind('click').click(function(e){ //go to particular message when menu title is clicked on
if (e.target.tagName=="A"){
clearTimeout(s.playtimer)
s.curmsg=parseInt(e.target.getAttribute('data-pos'))
expandticker.selectmsg($, s, s.curmsg)
if (!s.manual)
s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
e.preventDefault()
}
})
$menu.appendTo(document.body)
$menu.data('state', 'closed') //indicate menu is currently closed
s.$menu=$menu //remember $menu
s.$menulis=$lis //remember $menu LIs
},
positionbutton:function($, s){
var toffset=s.$ticker.offset()
var buttonpos=[toffset.left+this.buttonoffset[0], toffset.top+s.$ticker.outerHeight()+this.buttonoffset[1]]
s.$button.css({left:buttonpos[0], top:buttonpos[1]})
},
addexpandbutton:function($, s){
s.$button=$(this.buttonhtml).css({position:'absolute', zIndex:1000}).appendTo(document.body) //create expand button, add it to page, and remember it
this.positionbutton($, s)
this.adddropmenu($, s)
s.$button.unbind('click').bind('click', function(e){ //show menu when expand button is clicked
s.$menu.css({left:s.$button.css('left'), top:parseInt(s.$button.css('top'))-expandticker.buttonoffset[1]}).show()
s.$menulis.removeClass('selected').eq(s.curmsg).addClass('selected') //highlight current message within menu
s.$menu.data('state', 'open') //indicate menu is open
e.stopPropagation()
})
},
selectmsg:function($, s, selected){
s.$contents.stop(true,true).hide().eq(selected)[s.effectfunct](s.timers.fxduration, function(){ //animate message into view
if (this.style && this.style.removeAttribute)
this.style.removeAttribute('filter') //fix IE clearType problem when animation is fade-in
})
s.curmsg=selected
if (s.$menu.data('state')=="open")
s.$menulis.removeClass('selected').eq(selected).addClass('selected') //highlight current message within menu
},
rotatemsg:function($, s){
if (s.$ticker.data('state')=="over"){ //pause ticker onMouseover
clearTimeout(s.pausetimer)
s.pausetimer=setTimeout(function(){expandticker.rotatemsg($, s)}, 100)
return
}
s.nextmsg=(s.curmsg<s.msglength-1)? s.curmsg+1 : 0 //go to next message
this.selectmsg($, s, s.nextmsg)
s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
},
setup:function($, s){
s.$contents=s.$ticker.find('.expandcontent').hide()
s.msglength=s.$contents.length
s.curmsg=0
expandticker.addexpandbutton($, s)
expandticker.selectmsg($, s, s.curmsg)
if (!s.manual){
s.$ticker.unbind('mouseenter').bind('mouseenter', function(){$(this).data('state', 'over')})
s.$ticker.unbind('mouseleave').bind('mouseleave', function(){$(this).data('state', 'out')})
s.playtimer=setTimeout(function(){expandticker.rotatemsg($, s)}, s.timers.rotatepause)
}
},
init:function(setting){
jQuery(document).ready(function($){ //fire on DOM ready
var s=setting
s=jQuery.extend({}, expandticker.dsetting, s)
s.timers.rotatepause+=s.timers.fxduration //add slide duration to rotate timer
s.$ticker=$('#'+s.id)
if (s.$ticker.length==0)
return
s.effectfunct=s.fx=="fade"? expandticker.effectfuncts[0] : expandticker.effectfuncts[1]
if (s.remotecontent && s.remotecontent[0].length>0){
s.remotecontent[1]=s.remotecontent[1]*1000 //convert units into seconds
expandticker.fetchajaxcontent($, s)
}
else
expandticker.setup($, s)
$(window).bind('load resize', function(e){ //reposition enlarge images when window has loaded or is resized
if (s.$button)
setTimeout(function(){expandticker.positionbutton($, s)}, (e.type=="load")? 200 : 0)
})
$(document).click(function(){
if (s.$menu){ //hide menu when user clicks anywhere on page
s.$menu.hide()
s.$menu.data('state', 'closed')
}
})
})
}
}
</script>
<script>
expandticker.init({
id: 'expandticker1',
snippetlength: 25,
fx: 'slide',
timers: {rotatepause:3000, fxduration:500} //--No comma following last option!
})
</script>