Index: openacs-4/packages/xowiki/xowiki.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/xowiki.info,v diff -u -r1.44 -r1.45 --- openacs-4/packages/xowiki/xowiki.info 19 Feb 2007 10:01:28 -0000 1.44 +++ openacs-4/packages/xowiki/xowiki.info 25 Feb 2007 09:57:09 -0000 1.45 @@ -8,11 +8,11 @@ f xowiki - + Gustaf Neumann A more generic xotcl-based wikis example with object types and subtypes based on the content repository (with category support) - 2007-02-19 + 2007-02-25 <pre> XoWiki is a wiki implementation for OpenACS in XOTcl. Instead of trying to implement the full set of wiki markup commands of systems @@ -91,20 +91,22 @@ 0.45: auto-naming of pages 0.46: support for announcement style configuration + +0.47: podcast support </pre> BSD-Style 0 - + - + Index: openacs-4/packages/xowiki/catalog/xowiki.en_US.ISO-8859-1.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/catalog/xowiki.en_US.ISO-8859-1.xml,v diff -u -r1.15 -r1.16 --- openacs-4/packages/xowiki/catalog/xowiki.en_US.ISO-8859-1.xml 30 Jan 2007 11:36:07 -0000 1.15 +++ openacs-4/packages/xowiki/catalog/xowiki.en_US.ISO-8859-1.xml 25 Feb 2007 09:57:09 -0000 1.16 @@ -1,5 +1,5 @@ - + Admin Back @@ -9,7 +9,7 @@ Delete Description Edit - edit + edit tags Index Language Name @@ -24,6 +24,7 @@ References to this Page: Revisions Search + Subtitle Title View more... Index: openacs-4/packages/xowiki/tcl/package-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/package-procs.tcl,v diff -u -r1.38 -r1.39 --- openacs-4/packages/xowiki/tcl/package-procs.tcl 19 Feb 2007 10:01:28 -0000 1.38 +++ openacs-4/packages/xowiki/tcl/package-procs.tcl 25 Feb 2007 09:57:09 -0000 1.39 @@ -108,6 +108,7 @@ Package ad_instproc pretty_link { {-anchor ""} {-absolute:boolean false} + {-siteurl ""} {-lang ""} name } { @@ -129,7 +130,7 @@ } } } - set host [expr {$absolute ? [ad_url] : ""}] + set host [expr {$absolute ? ($siteurl ne "" ? $siteurl : [ad_url]) : ""}] if {$anchor ne ""} {set anchor \#$anchor} #my log "--LINK $lang == $default_lang [expr {$lang ne $default_lang}] $name" @@ -254,12 +255,15 @@ Package instproc resolve_page {object method_var} { upvar $method_var method my instvar folder_id id policy + # + # first, resolve package level methods + # if {$object eq ""} { set exported [$policy defined_methods Package] foreach m $exported { #my log "--QP my exists_query_parameter $m = [my exists_query_parameter $m]" if {[::xo::cc exists_query_parameter $m]} { - set method $m ;# the only reason for the upvar + set method $m ;# determining the method, similar file extensions return [self] } } @@ -275,8 +279,11 @@ # we have no object, but as well no method callable on the package set object [$id get_parameter index_page "index"] } + # + # second, resolve object level methods + # #my log "--o try index '$object'" - set page [my resolve_request -path $object] + set page [my resolve_request -path $object method] #my log "--o page is '$page'" if {$page ne ""} { return $page @@ -290,7 +297,7 @@ set standard_page [$id get_parameter ${object}_page] #my log "--o standard_page '$standard_page'" if {$standard_page ne ""} { - set page [my resolve_request -path $standard_page] + set page [my resolve_request -path $standard_page method] if {$page ne ""} { return $page } @@ -299,7 +306,7 @@ set standard_page "en:$stripped_object" # maybe we are calling from a different language, but the # standard page with en: was already instantiated - set page [my resolve_request -path $standard_page] + set page [my resolve_request -path $standard_page method] if {$page ne ""} { return $page } @@ -358,7 +365,7 @@ } } - Package instproc resolve_request {-path} { + Package instproc resolve_request {-path method_var} { my instvar folder_id #my log "--u [self args]" [self class] instvar queryparm @@ -374,6 +381,13 @@ set name ${lang}:$local_name set item_id [::Generic::CrItem lookup -name $name -parent_id $folder_id] my log "--try $name -> $item_id // ::Generic::CrItem lookup -name $name -parent_id $folder_id" + if {$item_id == 0 && $lang eq "file" && [regexp {(.+)/download.} $local_name _ base_name]} { + set item_id [::Generic::CrItem lookup -name file:$base_name -parent_id $folder_id] + if {$item_id != 0} { + upvar $method_var method + set method download + } + } if {$item_id == 0 && $lang eq "file"} { set item_id [::Generic::CrItem lookup -name image:$local_name -parent_id $folder_id] my log "--try image:$local_name -> $item_id" @@ -587,41 +601,6 @@ # # RSS 2.0 support # - - Package instproc rss_head { - -channel_title - -link - -description - {-language en-us} - } { -# - return " - - - $channel_title - $link - $description - $language - xowiki" - } - - Package instproc rss_item {-creator -title -link -guid -description -pubdate } { - append result \n\ - $creator \n\ - $title \n\ - $link \n\ - "" $guid \n\ - $description \n\ - $pubdate \n\ - \n - } - - Package instproc rss_tail {} { - return "\n\n\n" - } - Package ad_instproc rss { -maxentries -name_filter @@ -638,73 +617,34 @@ } { set package_id [my id] - set folder_id [::$package_id folder_id] - set extra_where_clause "" - - if {![info exists days] && - [regexp {[^0-9]*([0-9]+)d} [my query_parameter rss] _ days]} { - # setting the variable days - } + set folder_id [$package_id folder_id] if {![info exists namefilter]} { set name_filter [my get_parameter name_filter ""] } - if {$name_filter ne ""} { - append extra_where_clause "and ci.name ~ E'$name_filter' " - } + if {![info exists title]} { set title [my get_parameter title ""] if {$title eq ""} { set title [::$folder_id set title] } } - my log "--rss: title=$title" - set limit_clause [expr {[info exists maxentries] ? " limit $maxentries" : ""}] - set timerange_clause [expr {[info exists days] ? - " and p.last_modified > (now() + interval '$days days ago')" : ""}] - - set xmlMap { & & < < > > \" " ' ' } + if {![info exists days] && + [regexp {[^0-9]*([0-9]+)d} [my query_parameter rss] _ days]} { + # setting the variable days + } else { + set days 10 + } - set content [my rss_head \ - -channel_title [string map $xmlMap $title] \ - -description [string map $xmlMap [::$folder_id set description]] \ - -link [ad_url][site_node::get_url_from_object_id -object_id $package_id] \ - ] + set r [RSS new -destroy_on_cleanup \ + -package_id [my id] \ + -name_filter $name_filter \ + -title $title \ + -days $days] - db_foreach get_pages \ - "select s.body, p.name, p.creator, p.title, p.page_id,\ - p.object_type as content_type, p.last_modified, p.description \ - from xowiki_pagex p, syndication s, cr_items ci \ - where ci.parent_id = $folder_id and ci.live_revision = s.object_id \ - and ci.publish_status <> 'production' $extra_where_clause \ - and s.object_id = p.page_id $timerange_clause \ - order by p.last_modified desc $limit_clause \ - " { - - if {[string match "::*" $name]} continue - if {$content_type eq "::xowiki::PageTemplate::"} continue - - set description [string trim $description] - if {$description eq ""} {set description $body} - regexp {^([^.]+)[.][0-9]+(.*)$} $last_modified _ time tz - - if {$title eq ""} {set title $name} - #append title " ($content_type)" - set time "[clock format [clock scan $time] -format {%a, %d %b %Y %T}] ${tz}00" - append content [my rss_item \ - -creator [string map $xmlMap $creator] \ - -title [string map $xmlMap $title] \ - -link [::$package_id pretty_link -absolute true $name] \ - -guid [ad_url]/$page_id \ - -description [string map $xmlMap $description] \ - -pubdate $time \ - ] - } - - append content [my rss_tail] #set t text/plain set t text/xml - ns_return 200 $t $content + ns_return 200 $t [$r render] } # Index: openacs-4/packages/xowiki/tcl/syndicate-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/syndicate-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/xowiki/tcl/syndicate-procs.tcl 25 Feb 2007 09:57:09 -0000 1.1 @@ -0,0 +1,225 @@ +namespace eval ::xowiki { + # + # RSS 2.0 support + # + + Class RSS -parameter { + package_id + maxentries + {name_filter ""} + {days ""} + {siteurl ""} + {description ""} + {language en-us} + {title ""} + } \ + -ad_doc { + Report content of xowiki folder in rss 2.0 format. The + reporting order is descending by date. The title of the feed + is taken from the title, the description + is taken from the description field of the folder object. + + @param maxentries maximum number of entries retrieved + @param days report entries changed in speficied last days + @param name_filter include only pages matching the provided regular expression (postgres) + + } + + RSS instproc init {} { + my set xmlMap [list & "&" < "<" > ">" \" """ ' "'"] + } + + RSS instproc tag {{-atts } name value} { + my instvar xmlMap + set attsXML "" + if {[info exists atts]} { + foreach {attName attValue} $atts { + append attsXML " $attName='$attValue'" + } + } + return <$name$attsXML>[string map $xmlMap $value] + } + + RSS instproc head {} { + my instvar title link description language +# + return " + + + [my tag title $title] + [my tag link $link] + [my tag description $description] + [my tag language $language] + [my tag generator xowiki]" + } + + RSS instproc item {-creator -title -link -guid -description -pubdate } { + append result \n\ + [my tag dc:creator $creator ] \n\ + [my tag title $title ] \n\ + [my tag link $link ] \n\ + [my tag -atts {isPermaLink false} guid $guid] \n\ + [my tag description $description ] \n\ + [my tag pubDate $pubdate ] \n\ + \n + } + + RSS instproc tail {} { + return "\n\n\n" + } + + + RSS instproc limit_clause {} { + my instvar maxentries + if {[info exists maxentries] && $maxentries ne ""} { + return " limit $maxentries" + } + return "" + } + + RSS instproc extra_where_clause {} { + my instvar name_filter days + set extra_where_clause "" + if {$name_filter ne ""} { + append extra_where_clause " and ci.name ~ E'$name_filter' " + } + if {$days ne ""} { + append extra_where_clause " and p.last_modified > (now() + interval '$days days ago')" + } + return $extra_where_clause + } + + RSS instproc render {} { + my instvar package_id max_entries name_filter title days description siteurl + set folder_id [::$package_id folder_id] + + if {$description eq ""} {set description [::$folder_id set description]} + set url [expr {[my exists siteurl] ? $siteurl : [ad_url]}] + my set link $url[site_node::get_url_from_object_id -object_id $package_id] + + set content [my head] + db_foreach get_pages \ + "select s.body, p.name, p.creator, p.title, p.page_id,\ + p.object_type as content_type, p.last_modified, p.description \ + from xowiki_pagex p, syndication s, cr_items ci \ + where ci.parent_id = $folder_id and ci.live_revision = s.object_id \ + and ci.publish_status <> 'production' \ + [my extra_where_clause] \ + and s.object_id = p.page_id \ + order by p.last_modified desc [my limit_clause] \ + " { + + if {[string match "::*" $name]} continue + if {$content_type eq "::xowiki::PageTemplate"} continue + + set description [string trim $description] + if {$description eq ""} {set description $body} + regexp {^([^.]+)[.][0-9]+(.*)$} $last_modified _ time tz + + if {$title eq ""} {set title $name} + set url [expr {[my exists siteurl] ? [my set siteurl] : [ad_url]}] + #append title " ($content_type)" + set time "[clock format [clock scan $time] -format {%a, %d %b %Y %T}] ${tz}00" + append content [my item \ + -creator $creator \ + -title $title \ + -link [::$package_id pretty_link -absolute true -siteurl [my siteurl] $name] \ + -guid $url/$page_id \ + -description $description \ + -pubdate $time \ + ] + } + + append content [my tail] + return $content + } + + Class Podcast -superclass RSS -parameter { + {subtitle ""} + {description ""} + {summary ""} + {author ""} + {explicit "no"} + } + + Podcast instproc head {} { + my instvar title link description language subtitle summary author explicit +# + return " + + + [my tag title $title] + [my tag link $link] + [my tag description $description] + [my tag language $language] + [my tag generator xowiki] + [my tag itunes:subtitle $subtitle] + [my tag itunes:summary $summary] + [my tag itunes:author $author] + [my tag itunes:explicit $explicit] +" + } + + Podcast instproc item { + -author -title -subtitle + -link -guid -pubdate + -mime_type -duration -keywords} { + append result \n \ + [my tag title $title] \n\ + [my tag link $link ] \n\ + [my tag -atts {isPermaLink true} guid $guid] \n\ + [my tag pubDate $pubdate] \n\ + [my tag itunes:duration $duration] \n\ + [my tag author $author ] \n\ + [my tag itunes:subtitle $subtitle ] \n\ + [my tag itunes:author $author ] \n\ + [my tag itunes:keywords $keywords ] \n\ + " " \ + \n \n + } + + + Podcast instproc render {} { + my instvar package_id max_entries name_filter title days \ + summary subtitle description author + + set folder_id [::$package_id folder_id] + if {$description eq ""} {set description [::$folder_id set description]} + if {$summary eq ""} {set summary $description} + if {$subtitle eq ""} {set subtitle $title} + + set url [expr {[my exists siteurl] ? [my set siteurl] : [ad_url]}] + my set link $url[site_node::get_url_from_object_id -object_id $package_id] + + set content [my head] + db_foreach get_pages \ + "select * from xowiki_podcast_itemi p, cr_items ci, cr_mime_types m \ + where ci.parent_id = $folder_id and ci.item_id = p.item_id \ + and ci.live_revision = p.object_id \ + and p.mime_type = m.mime_type \ + and ci.publish_status <> 'production' [my extra_where_clause] \ + order by p.last_modified desc [my limit_clause] \ + " { + + if {$content_type ne "::xowiki::PodcastItem"} continue + + #regexp {^([^.]+)[.][0-9]+(.*)$} $last_modified _ time tz + + if {$title eq ""} {set title $name} + #set time "[clock format [clock scan $time] -format {%a, %d %b %Y %T}] ${tz}00" + set link [::$package_id pretty_link -absolute true -siteurl [my siteurl] $name]/download.$file_extension + append content [my item \ + -author $creator -title $title -subtitle $subtitle \ + -link $link -mime_type $mime_type \ + -guid $link -pubdate $pub_date -duration $duration \ + -keywords $keywords] + } + + append content [my tail] + return $content + } + + +} \ No newline at end of file Index: openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl,v diff -u -r1.30 -r1.31 --- openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl 19 Feb 2007 10:01:28 -0000 1.30 +++ openacs-4/packages/xowiki/tcl/xowiki-form-procs.tcl 25 Feb 2007 09:57:09 -0000 1.31 @@ -148,19 +148,18 @@ my instvar data my log "--F validate_name ot=$object_type data=[my exists data]" $data instvar package_id - if {$object_type eq "::xowiki::File" && [$data exists mime_type]} { + if {[lsearch [$object_type info heritage] ::xowiki::File] > -1 && [$data exists mime_type]} { + #my get_uploaded_file #my log "--mime validate_name ot=$object_type data=[my exists data] MIME [$data set mime_type]" set mime [$data set mime_type] set fn [$data set upload_file] - #my log "--mime=$mime" switch -- $mime { application/force-download { set mime [::xowiki::guesstype $fn] $data set mime_type $mime } } - #my log "--mime 2 = $mime" switch -glob -- $mime { image/* {set type image} default {set type file} @@ -203,19 +202,20 @@ } } WikiForm instproc update_references {} { - my instvar data + my instvar data folder_id if {![my istype PageInstanceForm]} { ### danger: update references does an ad_eval, which breaks the [template::adp_level] ### ad_form! don't do it in pageinstanceforms. $data render_adp false $data render -update_references } - # delete the link cache entries for this item - # could be made more intelligent to delete entries is more rare cases, like - # in case the file was renamed - my instvar folder_id - ##### why is ns_cache names xowiki_cache *pattern* not working??? - ##### upgrade ns_cache from CVS ! + # Delete the link cache entries for this entry. + # The logic could be made more intelligent to delete entries is more rare cases, like + # in case the file was renamed, but this is more bullet-proove. + # + # In case "ns_cache names xowiki_cache *pattern*" is not working on your installation; + # upgrade ns_cache from cvs or use + # foreach entry [lsearch -inline -all [ns_cache names xowiki_cache] link-*-$folder_id] foreach entry [ns_cache names xowiki_cache link-*-$folder_id] { array set tmp [ns_cache get xowiki_cache $entry] if {$tmp(item_id) == [$data set item_id]} { @@ -296,7 +296,7 @@ {html { enctype multipart/form-data }} \ {field_list {item_id name text title creator description}} {f.name - {name:text,nospell,optional + {name:text,nospell,optional {label #xowiki.name#} {help_text {Can be obtained from the name of the uploaded file}}}} {f.title {title:text,optional {label #xowiki.title#} {html {size 80}} }} @@ -342,6 +342,73 @@ return [next] } + + Class create PodcastForm -superclass FileForm \ + -parameter { + {html { enctype multipart/form-data }} \ + {field_list {item_id name text title subtitle creator pub_date duration keywords + description}} + {f.subtitle + {subtitle:text,nospell,optional {label #xowiki.subtitle#} {html {size 80}}}} + {f.pub_date + {pub_date:date,optional {format "YYYY MM DD HH24 MI"} {html {id date}} + {after_html { Y-M-D} + }} + } + {f.duration + {duration:text,nospell,optional + {help_text {E.g. 9:16 means 9 minutes 16 seconds}} + }} + {f.keywords + {keywords:text,nospell,optional + {help_text {comma separated itunes keywords, e.g. salt, pepper, shaker, exciting}} + }} + {validate { + {upload_file {\[::xowiki::validate_file\]} {For new entries, \ + a upload file must be provided}} + {name {\[::xowiki::validate_name\]} {Another item with this name exists \ + already in this folder}} + }} + } + + PodcastForm instproc to_timestamp {widgetinfo} { + if {$widgetinfo ne ""} { + foreach {y m day hour min} $widgetinfo break + set t [clock scan "${hour}:$min $m/$day/$y"] + return [clock format $t] + } + return "" + } + PodcastForm instproc to_timeinfo {timestamp} { + set t [clock scan $timestamp] + return "[clock format $t -format {%Y %m %d %H %M}] {} {YY MM DD HH24 MI}" + } + + PodcastForm instproc new_data {} { + set pub_date [my var pub_date] + my var pub_date [list [my to_timestamp $pub_date]] + return [next] + } + PodcastForm instproc edit_data {} { + set pub_date [my var pub_date] + my var pub_date [list [my to_timestamp $pub_date]] + return [next] + } + + PodcastForm instproc new_request {} { + my instvar data + $data set pub_date [my to_timeinfo [clock format [clock seconds]]] + next + } + PodcastForm instproc edit_request {item_id} { + my instvar data + $data set pub_date [my to_timeinfo [$data set pub_date]] + next + } + + # # Object Form # Index: openacs-4/packages/xowiki/tcl/xowiki-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-procs.tcl,v diff -u -r1.75 -r1.76 --- openacs-4/packages/xowiki/tcl/xowiki-procs.tcl 19 Feb 2007 10:01:28 -0000 1.75 +++ openacs-4/packages/xowiki/tcl/xowiki-procs.tcl 25 Feb 2007 09:57:09 -0000 1.76 @@ -37,6 +37,22 @@ -storage_type file \ -form ::xowiki::FileForm + ::Generic::CrClass create PodcastItem -superclass File \ + -pretty_name "Podcast Item" -pretty_plural "Podcase Items" \ + -table_name "xowiki_podcast_item" -id_column "podcast_item_id" \ + -cr_attributes { + ::Generic::Attribute new -attribute_name pub_date -datatype date -sqltype timestamp \ + -pretty_name "Publication Date" + ::Generic::Attribute new -attribute_name duration -datatype text \ + -pretty_name "Duration" + ::Generic::Attribute new -attribute_name subtitle -datatype text \ + -pretty_name "Subtitle" + ::Generic::Attribute new -attribute_name keywords -datatype text \ + -pretty_name "Keywords" + } \ + -storage_type file \ + -form ::xowiki::PodcastForm + ::Generic::CrClass create PageTemplate -superclass Page \ -pretty_name "XoWiki Page Template" -pretty_plural "XoWiki Page Templates" \ -table_name "xowiki_page_template" -id_column "page_template_id" \ @@ -682,7 +698,7 @@ set t [TableWidget new -volatile \ -columns { AnchorField name -label [_ xowiki.name] - Field mime_type -label [_ xowiki.page_type] + Field mime_type -label "Content Type" Field last_modified -label "Last Modified" Field mod_user -label "By User" Field size -label "Size" Index: openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl,v diff -u -r1.38 -r1.39 --- openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl 19 Feb 2007 10:01:28 -0000 1.38 +++ openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl 25 Feb 2007 09:57:09 -0000 1.39 @@ -165,7 +165,7 @@ set my_yahoo_link "http://us.rd.yahoo.com/my/atm/$my_yahoo_publisher/$feedname/*http://add.my.yahoo.com/rss?url=$rssurl" } - set master [my query_parameter "master" 1] + set master [$package_id get_parameter "master" 1] #if {[my exists_query_parameter "edit_return_url"]} { # set return_url [my query_parameter "edit_return_url"] #} Index: openacs-4/packages/xowiki/www/prototypes/podcast.page =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/prototypes/podcast.page,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/xowiki/www/prototypes/podcast.page 25 Feb 2007 09:57:09 -0000 1.1 @@ -0,0 +1,30 @@ +# -*- tcl-*- +# $Id: podcast.page,v 1.1 2007/02/25 09:57:09 gustafn Exp $ +::xowiki::Object new -title "XoWiki Podcast" -text { + + my initialize -parameter { + {-name_filter ""} + {-days ""} + } + + proc content {} { + my get_parameters + + ::xo::cc set_parameter master 0 + if {$title eq ""} {set title [[my info parent] title]} + set f [::xowiki::Podcast new -destroy_on_cleanup \ + -package_id $package_id \ + -name_filter $name_filter \ + -siteurl http://localhost:8053 \ + -title [[my info parent] set title] \ + -description [[my info parent] set description] \ + -author [[my info parent] creator] \ + -subtitle "A Sample Collection of Podcast Items" \ + -days $days] + + return [$f render] + } +} + + + Index: openacs-4/packages/xowiki/www/resources/cattree.css =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/resources/cattree.css,v diff -u -r1.2 -r1.3 --- openacs-4/packages/xowiki/www/resources/cattree.css 30 Apr 2006 23:53:35 -0000 1.2 +++ openacs-4/packages/xowiki/www/resources/cattree.css 25 Feb 2007 09:57:09 -0000 1.3 @@ -9,7 +9,7 @@ /* Show "bullets" in the links, depending on the class of the LI that the link's in */ ul.mktree li.liOpen .bullet { cursor: pointer; background: url(/resources/acs-templating/minus.gif) center left no-repeat; } ul.mktree li.liClosed .bullet { cursor: pointer; background: url(/resources/acs-templating/plus.gif) center left no-repeat; } - ul.mktree li.liBullet .bullet { cursor: default; background: url(/resources/acs-templating/bullet.gif) center left no-repeat; } + ul.mktree li.liBullet .bullet { margin-left:-15px; padding-left:10px; cursor: default; background: url(/resources/acs-templating/bullet.gif) center left no-repeat; } /* Sublists are visible or not based on class of parent LI */ ul.mktree li.liOpen ul { display: block; } ul.mktree li.liClosed ul { display: none; }