Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

first commit

  • Loading branch information...
commit 53696c2e63d2851fe7bc561237b77510fa12b4bc 0 parents
@fdv fdv authored
20 MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Frédéric de Villamil
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14 README
@@ -0,0 +1,14 @@
+Typo Sliding Posts
+==================
+
+This plugin is – obviously – a carousel for Typo, the famous Ruby on Rails blogging system avaliable at http://typosphere.org
+
+Typo carousel displays featured posts at the topcontent on your blog homepage grabbing pictures from the post.
+
+Example
+=======
+
+Installing Typo Sliding Posts is pretty easy
+
+
+Copyright (c) 2009 Frédéric de Villamil, released under the MIT license
23 Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the typo sliding posts plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the typo sliding posts plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'TypoCarousel'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
BIN  images/carousel_next.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  images/carousel_previous.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 init.rb
@@ -0,0 +1,4 @@
+require 'typo_sliding_posts'
+
+ActionController::Base.send :include, TypoSlidingPosts
+ActionController::Base.send :helper, TypoSlidingPostsHelper
9 install.rb
@@ -0,0 +1,9 @@
+source = File.join(RAILS_ROOT, '/vendor/plugins/typo_sliding_posts/')
+destination = File.join(RAILS_ROOT, '/public/')
+
+puts "Copying Typo sliding posts files"
+File.copy(File.join(source, 'javascripts/carousel.js'), File.join(destination, 'javascripts/carousel.js'))
+File.copy(File.join(source, 'images/carousel_previous.png'), File.join(destination, 'images/carousel_previous.png'))
+File.copy(File.join(source, 'images/carousel_next.png'), File.join(destination, 'images/carousel_next.png'))
+puts "Done"
+
327 javascripts/carousel.js
@@ -0,0 +1,327 @@
+/*
+Copyright (c) 2009 Victor Stanciu - http://www.victorstanciu.ro
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+Carousel = Class.create(Abstract, {
+ initialize: function (scroller, slides, controls, options) {
+ this.scrolling = false;
+ this.scroller = $(scroller);
+ this.slides = slides;
+ this.controls = controls;
+
+ this.options = Object.extend({
+ duration: 1,
+ auto: false,
+ frequency: 3,
+ visibleSlides: 1,
+ controlClassName: 'carousel-control',
+ jumperClassName: 'carousel-jumper',
+ disabledClassName: 'carousel-disabled',
+ selectedClassName: 'carousel-selected',
+ circular: false,
+ wheel: true,
+ effect: 'scroll',
+ transition: 'sinoidal'
+ }, options || {});
+
+ if (this.options.effect == 'fade') {
+ this.options.circular = true;
+ }
+
+ this.slides.each(function(slide, index) {
+ slide._index = index;
+ });
+
+ if (this.controls) {
+ this.controls.invoke('observe', 'click', this.click.bind(this));
+ }
+
+ if (this.options.wheel) {
+ this.scroller.observe('mousewheel', this.wheel.bindAsEventListener(this)).observe('DOMMouseScroll', this.wheel.bindAsEventListener(this));;
+ }
+
+ if (this.options.auto) {
+ this.start();
+ }
+
+ if (this.options.initial) {
+ var initialIndex = this.slides.indexOf($(this.options.initial));
+ if (initialIndex > (this.options.visibleSlides - 1) && this.options.visibleSlides > 1) {
+ if (initialIndex > this.slides.length - (this.options.visibleSlides + 1)) {
+ initialIndex = this.slides.length - this.options.visibleSlides;
+ }
+ }
+ this.moveTo(this.slides[initialIndex]);
+ }
+ },
+
+ click: function (event) {
+ this.stop();
+
+ var element = event.findElement('a');
+
+ if (!element.hasClassName(this.options.disabledClassName)) {
+ if (element.hasClassName(this.options.controlClassName)) {
+ eval("this." + element.rel + "()");
+ } else if (element.hasClassName(this.options.jumperClassName)) {
+ this.moveTo(element.rel);
+ if (this.options.selectedClassName) {
+ this.controls.invoke('removeClassName', this.options.selectedClassName);
+ element.addClassName(this.options.selectedClassName);
+ }
+ }
+ }
+
+ this.deactivateControls();
+
+ event.stop();
+ },
+
+ moveTo: function (element) {
+ if (this.options.beforeMove && (typeof this.options.beforeMove == 'function')) {
+ this.options.beforeMove();
+ }
+
+ this.previous = this.current ? this.current : this.slides[0];
+ this.current = $(element);
+
+ var scrollerOffset = this.scroller.cumulativeOffset();
+ var elementOffset = this.current.cumulativeOffset();
+
+ if (this.scrolling) {
+ this.scrolling.cancel();
+ }
+
+ switch (this.options.effect) {
+ case 'fade':
+ this.scrolling = new Effect.Opacity(this.scroller, {
+ from: 1.0,
+ to: 0,
+ duration: this.options.duration,
+ afterFinish: (function () {
+ this.scroller.scrollLeft = elementOffset[0] - scrollerOffset[0];
+ this.scroller.scrollTop = elementOffset[1] - scrollerOffset[1];
+
+ new Effect.Opacity(this.scroller, {
+ from: 0,
+ to: 1.0,
+ duration: this.options.duration,
+ afterFinish: (function () {
+ if (this.controls) {
+ this.activateControls();
+ }
+ if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
+ this.options.afterMove();
+ }
+ }).bind(this)
+ });
+ }
+ ).bind(this)});
+ break;
+ case 'scroll':
+ default:
+ var transition;
+ switch (this.options.transition) {
+ case 'spring':
+ transition = Effect.Transitions.spring;
+ break;
+ case 'sinoidal':
+ default:
+ transition = Effect.Transitions.sinoidal;
+ break;
+ }
+
+ this.scrolling = new Effect.SmoothScroll(this.scroller, {
+ duration: this.options.duration,
+ x: (elementOffset[0] - scrollerOffset[0]),
+ y: (elementOffset[1] - scrollerOffset[1]),
+ transition: transition,
+ afterFinish: (function () {
+ if (this.controls) {
+ this.activateControls();
+ }
+ if (this.options.afterMove && (typeof this.options.afterMove == 'function')) {
+ this.options.afterMove();
+ }
+ this.scrolling = false;
+ }).bind(this)});
+ break;
+ }
+
+ return false;
+ },
+
+ prev: function () {
+ if (this.current) {
+ var currentIndex = this.current._index;
+ var prevIndex = (currentIndex == 0) ? (this.options.circular ? this.slides.length - 1 : 0) : currentIndex - 1;
+ } else {
+ var prevIndex = (this.options.circular ? this.slides.length - 1 : 0);
+ }
+
+ if (prevIndex == (this.slides.length - 1) && this.options.circular && this.options.effect != 'fade') {
+ this.scroller.scrollLeft = (this.slides.length - 1) * this.slides.first().getWidth();
+ this.scroller.scrollTop = (this.slides.length - 1) * this.slides.first().getHeight();
+ prevIndex = this.slides.length - 2;
+ }
+
+ this.moveTo(this.slides[prevIndex]);
+ },
+
+ next: function () {
+ if (this.current) {
+ var currentIndex = this.current._index;
+ var nextIndex = (this.slides.length - 1 == currentIndex) ? (this.options.circular ? 0 : currentIndex) : currentIndex + 1;
+ } else {
+ var nextIndex = 1;
+ }
+
+ if (nextIndex == 0 && this.options.circular && this.options.effect != 'fade') {
+ this.scroller.scrollLeft = 0;
+ this.scroller.scrollTop = 0;
+ nextIndex = 1;
+ }
+
+ if (nextIndex > this.slides.length - (this.options.visibleSlides + 1)) {
+ nextIndex = this.slides.length - this.options.visibleSlides;
+ }
+
+ this.moveTo(this.slides[nextIndex]);
+ },
+
+ first: function () {
+ this.moveTo(this.slides[0]);
+ },
+
+ last: function () {
+ this.moveTo(this.slides[this.slides.length - 1]);
+ },
+
+ toggle: function () {
+ if (this.previous) {
+ this.moveTo(this.slides[this.previous._index]);
+ } else {
+ return false;
+ }
+ },
+
+ stop: function () {
+ if (this.timer) {
+ clearTimeout(this.timer);
+ }
+ },
+
+ start: function () {
+ this.periodicallyUpdate();
+ },
+
+ pause: function () {
+ this.stop();
+ this.activateControls();
+ },
+
+ resume: function (event) {
+ if (event) {
+ var related = event.relatedTarget || event.toElement;
+ if (!related || (!this.slides.include(related) && !this.slides.any(function (slide) { return related.descendantOf(slide); }))) {
+ this.start();
+ }
+ } else {
+ this.start();
+ }
+ },
+
+ periodicallyUpdate: function () {
+ if (this.timer != null) {
+ clearTimeout(this.timer);
+ this.next();
+ }
+ this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency * 1000);
+ },
+
+ wheel: function (event) {
+ event.cancelBubble = true;
+ event.stop();
+
+ var delta = 0;
+ if (!event) {
+ event = window.event;
+ }
+ if (event.wheelDelta) {
+ delta = event.wheelDelta / 120;
+ } else if (event.detail) {
+ delta = -event.detail / 3;
+ }
+
+ if (!this.scrolling) {
+ this.deactivateControls();
+ if (delta > 0) {
+ this.prev();
+ } else {
+ this.next();
+ }
+ }
+
+ return Math.round(delta); //Safari Round
+ },
+
+ deactivateControls: function () {
+ this.controls.invoke('addClassName', this.options.disabledClassName);
+ },
+
+ activateControls: function () {
+ this.controls.invoke('removeClassName', this.options.disabledClassName);
+ }
+});
+
+
+Effect.SmoothScroll = Class.create();
+Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
+ initialize: function (element) {
+ this.element = $(element);
+ var options = Object.extend({ x: 0, y: 0, mode: 'absolute' } , arguments[1] || {});
+ this.start(options);
+ },
+
+ setup: function () {
+ if (this.options.continuous && !this.element._ext) {
+ this.element.cleanWhitespace();
+ this.element._ext = true;
+ this.element.appendChild(this.element.firstChild);
+ }
+
+ this.originalLeft = this.element.scrollLeft;
+ this.originalTop = this.element.scrollTop;
+
+ if (this.options.mode == 'absolute') {
+ this.options.x -= this.originalLeft;
+ this.options.y -= this.originalTop;
+ }
+ },
+
+ update: function (position) {
+ this.element.scrollLeft = this.options.x * position + this.originalLeft;
+ this.element.scrollTop = this.options.y * position + this.originalTop;
+ }
+});
36 lib/typo_sliding_posts.rb
@@ -0,0 +1,36 @@
+require 'hpricot'
+module TypoSlidingPosts
+
+end
+
+module TypoSlidingPostsHelper
+ def render_carousel(articles)
+ i = 0
+ carousel = '<div id="carousel">'
+ carousel << '<a href="#" class="carousel-control" id="carousel-previous" rel="prev"><img src="/images/theme/fleche1.png" alt="Article précédent" /></a>'
+ carousel << '<a href="#" class="carousel-control" id="carousel-next" rel="next"><img src="/images/theme/fleche2.png" alt="Article suivant" /></a>'
+ carousel << '<div id="carousel-wrapper">'
+ carousel << '<div id="carousel-content">'
+ articles.each do |article|
+ doc = Hpricot(article.body)
+ (doc/"img[@class='carousel']").each do |img|
+ i = 1
+ carousel << "<div class='slide' style='background: url(#{img.attributes['src']});'>"
+ carousel << "<p class='carousel-overlay'>"
+ carousel << link_to_permalink(article, "#{article.title}<br /><small>#{article.body.strip_html.slice(0, 300)}")
+ carousel << "</small></p>"
+ carousel << '</div>'
+ end
+ end
+
+ carousel << '</div>'
+ carousel << '</div>'
+ carousel << '</div>'
+ carousel << '<script type="text/javascript">'
+ carousel << "new Carousel('carousel-wrapper', $$('#carousel-content .slide'), $$('a.carousel-control', 'a.carousel-jumper'), {duration: 0.4, circular: false});"
+ carousel << '</script>'
+ return carousel unless i == 0
+ end
+
+
+end
83 stylesheets/typo_sliding_posts.css
@@ -0,0 +1,83 @@
+#carousel {
+ width: 644px;
+ margin-top: 3px;
+ height: 195px;
+ overflow: hidden;
+ position: relative;
+ border: #000 3px solid;
+ margin-bottom: 30px;
+}
+
+#carousel-wrapper {
+ width: 650px;
+ height: 200px;
+ overflow: hidden;
+}
+
+#carousel-content {
+ width: 2000px;
+}
+#carousel-content .slide {
+ float: left;
+ width: 650px;
+ height: 195px;
+ padding-top: 135px;
+}
+
+#carousel-content .slide p {
+ bottom: 0;
+ color: #fff;
+ height: 60px;
+ margin: 0;
+ width: 650px;
+ line-height: 16px;
+ font-size: 18px;
+ font-family: "Trebuchet MS", Calibri, Helvetica, sans-serif;
+ cursor: pointer;
+}
+
+#carousel-content .slide p small {
+ font: 11px/16px "Lucida Sans Unicode", "Lucida Grande", Arial, sans-serif;
+}
+
+#carousel-content .slide p a {
+ color: #fff;
+ text-decoration: none;
+ display: block;
+ opacity:0.7;
+ filter:alpha(opacity=70);
+ background: #000;
+ padding: 5px 10px;
+}
+
+#carousel-content .slide p a:hover {
+ opacity:0.9;
+ filter:alpha(opacity=90);
+}
+
+a#carousel-previous,
+a#carousel-next {
+ position: absolute;
+ top: 50px;
+ opacity:0.2;
+ filter:alpha(opacity=20);
+}
+
+a#carousel-previous img,
+a#carousel-next img {
+ border: none;
+}
+
+a#carousel-previous:hover,
+a#carousel-next:hover {
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+
+a#carousel-previous {
+ left: 0;
+}
+
+#carousel-next {
+ right: 0;
+}
4 tasks/typo_sliding_posts_tasks.rake
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :typo_carousel do
+# # Task goes here
+# end
3  test/test_helper.rb
@@ -0,0 +1,3 @@
+require 'rubygems'
+require 'active_support'
+require 'active_support/test_case'
8 test/typo_sliding_posts_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class TypoCarouselTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
1  uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here
Please sign in to comment.
Something went wrong with that request. Please try again.