You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by br...@apache.org on 2014/02/14 18:24:35 UTC

svn commit: r1568367 [2/13] - in /jspwiki/trunk: ./ jspwiki-war/ jspwiki-war/src/main/config/wro/ jspwiki-war/src/main/java/org/apache/wiki/ jspwiki-war/src/main/scripts/dynamic-styles/ jspwiki-war/src/main/scripts/lib/ jspwiki-war/src/main/scripts/moo...

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.Slimbox.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.Slimbox.js?rev=1568367&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.Slimbox.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.Slimbox.js Fri Feb 14 17:24:32 2014
@@ -0,0 +1,292 @@
+/*
+Plugin: Viewer.Slimbox
+
+    Slimbox clone, refactored for JSPWiki.
+    Added support for iframes, flash video.
+    Todo: html5 video.
+
+Credits:
+    Inspired by Slimbox by Christophe Bleys, (see http://www.digitalia.be/software/slimbox)
+    the mediaboxAdvanced by John Einselen (see http://iaian7.com/webcode/mediaboxAdvanced)
+    and the diabox by Mike Nelson. (see https://github.com/mnelson/diabox)
+
+DOM structure:
+    DOM structure of the JSPWiki Slimbox viewer.
+    (start code)
+    div#slmbx
+        div.modal               //semi transparent screen overlay
+        div.viewport(.spin)     //img, object or iframe element is inserted here
+            a.controls.caption
+            a.controls.next
+            a.controls.prev
+            a.controls.close
+    (end)
+*/
+Viewer.Slimbox = new Class({
+
+    Implements: Options,
+    Binds: ['attach','key','update','resize'],
+
+    options: {
+        loop: true,  // (boolean) affects next/prev at last/first element 
+        width: 800,  // (int px) default width of the box
+        height: 600, // (int px) default height of the box
+        hints: {     // default controls
+            btn: 'Click to view {0}', 
+            close: '×',
+            next: '>',  //«  Next
+            prev: '<',  //»  Previous
+            nofm: '[{0}/{1}]',              //[page/#pages]
+            size: ' ({0}px × {1}px)',  // (height x width)
+            caption: ' Go to {0}'    
+        },
+        keys: {
+            close: ['esc','x','c'],
+            prev:  ['left','up','p'],
+            next:  ['enter','space','right','down','n']
+        }
+    },
+
+    initialize: function(options){
+
+        var self = this.setOptions(options),
+            hints = self.options.hints,
+            controls = 'a.controls.';
+
+        //helper function
+        function clickFn(){
+            if( this.match('.next')){ self.update(1); }
+            else if( this.match('.prev')){ self.update(-1); }
+            else { self.attach( /*O=close*/ ); }
+        }
+
+        $(document.body).grab([
+            'div.slmbx', { attach:self }, [
+                'div.slmodal',{ events:{ click:clickFn } }, 
+                'div.viewport', { attach:[self,'viewport'], events:{ 'click:relay(a)':clickFn } }, [
+                    //insert viewable iframe/object/img ...
+                    controls+'caption',
+                    controls+'next',  { html:hints.next },
+                    controls+'prev',  { html:hints.prev },
+                    controls+'close', { html:hints.close }
+                ]
+            ]
+        ].slick());
+
+    },
+
+    /*
+    Function: get
+        Retrieve DOM elements inside the slimbox container, based on a css selector.
+    Example:
+    >    this.get('a.next');
+    */
+    get: function( selector ){
+
+        return this.element.getElement(selector);
+
+    },
+
+    /*
+    Function: match
+        Check if the URL is recognized as a viewable object/image/html...
+    */
+    match: function(url){
+    
+        return Viewer.match(url,this.options);
+
+    },
+
+    /*
+    Function: watch
+        Install click handlers on a group of images/objects/media links,
+        and optionally add slimbox click-buttons.
+
+    Arguments:
+        elements - set of DOM elements
+        btn - (optional) slick selector to insert a slimbox button after each viewable link
+    Returns
+        set of DOM elements viewable via Slimbox    
+    Example
+    >   TheSlimbox.watch( $$('.slimbox a','a.slimbox-btn');  
+      
+    */
+    watch: function(elements, btn){
+    
+        var self = this, caption;
+        
+        elements = $$(elements).filter( function(el){
+            return self.match( el.src||el.href );
+        });
+
+        return elements.each( function(el,idx){
+
+            caption = el.get('text') || el.title || el.alt;
+
+            if( btn ){ 
+                el = btn.slick({ 
+                    href:el.src||el.href, 
+                    title: self.options.hints.btn.xsubs(caption) 
+                }).inject(el,'after');
+            }
+
+            el.addEvent('click', function(ev){ ev.stop(); self.show(elements,idx); });
+
+        });
+            
+    },
+
+
+    /*
+    Function: show
+        Start the image/media viewer for a set of elements.
+    Arguments
+        elements - set of DOM elements to be viewed
+        cursor - index of first items to be viewed
+    */
+    show: function( elements, cursor ){
+    
+        var self = this;
+        self.elements = elements;
+        self.cursor = cursor;
+        self.attach( 1 /*true*/ );
+        self.update( 0 );
+
+    },
+
+    /*
+    Function: attach
+        Attach or de-tach eventhandlers from the slimbox dialogs.
+        Display or hide the modal and viewport. (css class .show)
+    */
+    attach: function( open ){
+
+        var self = this,
+            fn = open ? 'addEvent' : 'removeEvent';
+
+        ['object', Browser.ie6 ? 'select' : 'embed'].each(function(tag) {
+            $$(tag).each( function(el){
+                if( open ) el._slimbox = el.style.visibility;
+                el.style.visibility = open ? 'hidden' : el._slimbox;
+            });
+        });
+
+        self.element.ifClass(open,'active');
+        self.reset();
+
+        document[fn]('keydown', self.key); //checkme: support arrow keys, etc.
+
+    },
+
+    reset: function(){
+
+        this.viewport.getElements(':not(.controls)').destroy();
+        this.preload = null;
+
+    },
+
+    /*
+    Function: key
+        Handle keystrokes.
+    */
+    key: function( event ){
+
+        var self = this,
+            keys = self.options.keys,
+            key = event.key;
+
+        //console.log('keydown ', key);
+        keys.close.contains(key) ? self.attach(/*O=close*/) :
+            keys.next.contains(key) ? self.update(1) :
+                keys.prev.contains(key) ? self.update(-1) :
+                    /*otherwise*/ key=0;
+
+        if(key) event.stop();
+
+    },
+
+    /*
+    Function: update
+        Updates the viewport and the controls with caption, next and previous links.
+        Implements cursor loop-around logic.
+
+    Arguments:
+        increment - move the cursor by increment, and display the new content
+    */
+    update: function( increment ){
+
+        var self = this,
+            options = self.options,
+            hints = options.hints,
+            elements = self.elements,
+
+            max = elements.length,
+            many = max > 1,
+
+            incr = function(num){
+                return options.loop ? (num >= max) ? 0 : (num < 0) ? max-1 : num : num;
+            },
+            cursor = incr( self.cursor+increment ).limit( 0, max-1 ), //new cursor value
+
+            el, url;
+
+        if( increment!=0 && (cursor == self.cursor)){ return; }
+
+        self.cursor = cursor;
+        self.get('.prev')[ (many && (incr(cursor-1) >= 0 )) ? 'show' : 'hide']();
+        self.get('.next')[ (many && (incr(cursor+1) < max)) ? 'show' : 'hide']();
+
+        el = elements[cursor];
+        url = el.href||el.src; //url = encodeURIComponent(url);
+
+        self.get('.caption').set({
+            href: url,
+            html: 
+                ( many ? hints.nofm.xsubs( cursor+1, max)  : '' ) +
+                hints.caption.xsubs( el.title || el.alt || el.get('text')/*||''*/)
+        });
+
+        self.viewport.addClass('loading');
+        //if( self.preload ){ self.preload.destroy(); self.preload = null;}
+        self.reset();
+        //alert('wait');
+        Viewer.preload( url, options, self.resize );
+
+    },
+
+    /*
+    Function: resize
+        Completes the resizing of the viewport, after loading the img, iframe or object.
+    */
+    resize: function( preload ){
+
+        var self = this,
+            isImage = preload.match('img'),
+            viewport = self.viewport,
+
+            wSize = window.getSize(),
+            width = preload.width.toInt().limit( 240, 0.9*wSize.x ).toInt(),
+            height = preload.height.toInt().min( 0.9*wSize.y ).toInt(),
+            caption = self.get('.caption');
+
+        self.preload = preload;
+
+        //append viewport dimensions in px to the caption
+        caption.set('html', caption.get('html') + self.options.hints.size.xsubs(width,height) );
+
+        // viewport has css set to { top:50%, left:50% } for automatic centered positioning
+        viewport
+            .removeClass('loading')
+            .setStyles({
+                backgroundImage: isImage ? 'url(' + preload.src + ')' : 'none',
+                //rely on css3 transitions... iso mootools morph
+                width:width, height:height, marginTop:-height/2, marginLeft:-width/2
+            });
+            //mootools transition, in case css3 would not be available
+            //.morph({ width:width, height:height, marginTop:-height/2, marginLeft:-width/2 });
+
+        if( !isImage ) viewport.grab( preload ); //now include the viewer in the dom
+
+    }
+
+});
\ No newline at end of file

Added: jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.js
URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.js?rev=1568367&view=auto
==============================================================================
--- jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.js (added)
+++ jspwiki/trunk/jspwiki-war/src/main/scripts/dynamic-styles/Viewer.js Fri Feb 14 17:24:32 2014
@@ -0,0 +1,293 @@
+/*
+Viewer object
+    match(url,options): function to retrieve the media parms based on a url
+    preload(url,options,callback): preloads (created DOM object) the correct viewer
+        with the correct rendering paramaters (eg: used by Viewer.Slimbox)
+    preloads(elements,options,callback): preloads a set of viewer objects,
+        and calculates the minimals viewer-box dimensions (eg: used by Viewer.Carousel)
+    
+    LIB: data-array of pairs [['re1',{parms1}],['re2',{parms2}],..]
+        used by match() and preload() to identify the correct viewer & parameters.
+        This array can be customised and extended.
+        
+        regexp - (string) match against the url
+        parms - (function or object) returns the viewer parameters
+            'img' - to be rendered as IMG, directly in the browser
+            'url' - to be rendered as OBJECT (eg flash)
+            'src' - to be rendered as IFRAME
+            other-parameters with additional details
+*/
+!function(){
+
+this.Viewer = {
+
+    LIB: [],
+
+    match: function(url, options){
+
+        var result = {};
+
+        if( typeOf(url)=='element' ) url = url.src || url.href;
+
+        this.LIB.some( function(item){
+
+            return url.test( item[0], 'i' )
+                //item[1] can be a value or a function(url,options)
+                && (result = Function.from(item[1])(url, options) );
+
+        });
+
+        //options.type = 'img'|'url'|'src' 
+        //options.type = 'img';
+        //console.log(options.type);
+        if( options.type && !result[options.type] ) return false
+
+
+        return result;
+    },
+
+
+    preload: function(element, options, callback ){
+
+        var match = this.match(element, options),
+            preload;
+
+        function done(){
+            //console.log( match.width, preload.width.toInt(), match.height, preload.height.toInt(), preload);
+            if( callback ) callback( preload, preload.width.toInt(), preload.height.toInt() );
+        }
+
+        options = {
+            id: 'VIEW.' + String.uniqueID(), 
+            width:options.width, 
+            height:options.height 
+        };
+
+        if( match.img ){
+
+            preload = new Image();
+            preload.onload = done;  //delayed onload to know height&width of the image
+            preload.alt = element.alt;
+            //preload.title = element.title;
+            preload.src = match.img;
+
+        } else {
+        
+            //ffs: add branch for html5 enabled browsers & html5 enabled video sources
+            //if( match.url5 ) ...
+            if( match.url ){
+
+                preload = $(new Swiff( match.url, Object.merge(options, {
+                    params: {
+                        wmode: 'transparent',//'opaque', //'direct',
+                        //bgcolor: '#FFFFFF',
+                        allowfullscreen: 'true',
+                        allowscriptaccess: 'always'
+                    }
+                }, match ) ) );
+
+            } else if( match.src ){
+
+                preload = new IFrame( Object.merge( options, match, { frameborder:0 }));
+                //The actual loading starts only when the iframe gets added to the dom
+                //By default, the iframe is hidden during loading. (see Viewer.less)
+                document.body.adopt(preload);
+
+            } else {
+    
+                preload = new Element('p.error[html="Error"]');
+
+            }
+ 
+            done.delay(1); //sniff callback
+
+        }
+        //console.log("PRELOAD ", typeOf( preload ), preload );
+
+    },
+
+    preloads:function(elements, options, callback){
+
+        var countdown = elements.length, //counting the preloaded objects !
+            preloads = [],
+            w = options.width,
+            h = options.height;
+
+        if( !countdown ) return this.preload(elements, options, callback);
+
+        while( elements[0] ){
+
+            this.preload( elements.shift(), options, function(preload, width, height){
+
+                preloads.push( preload );
+                w = w.max(width);
+                h = h.max(height.toInt());
+//console.log("preloads.length, w,h);
+                if( !--countdown && callback ) callback( preloads, w, h );
+
+            });
+
+        }
+
+    }
+
+}
+
+var AdobeFlashPlayer = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
+
+Viewer.LIB.append([
+
+    ['.(bmp|gif|png|jpg|jpeg|tiff)$', function(url){
+        return { img:url }
+    }],
+
+    //google viewer for common formats
+    ['.(tiff|pdf|doc|docx|xls|xlsx|ppt|pptx|zip|rar)$',function(url){
+        return {
+            src:'http://docs.google.com/viewer?embedded=true&url=' + encodeURIComponent(url), //url,
+            width:850,
+            height:500
+        }
+    }],
+
+    //google maps
+    ['^https?://maps.google.com/maps',function(url){
+
+        //href="https://maps.google.com/maps?q=Atomium,%20City%20of%20Brussels,%20Belgium&amp;output=embed"
+        return {
+            src: url + '&output=embed',
+            width:850,
+            height:500,
+            scrolling:'no' 
+        }
+
+    }],
+
+
+    //add some mp3/audio player here
+
+    ['facebook.com', function(url){
+          url = 'http://www.facebook.com/v/' + url.split('v=')[1].split('&')[0];
+          return {
+            url:url,
+            movie:url,
+            classid: AdobeFlashPlayer,
+            width:756, //320,
+            height:424 //240
+        }
+    }],
+
+    ['flickr.com', function(url){
+        return {
+            url: 'http://www.flickr.com/apps/video/stewart.swf',
+            classid: AdobeFlashPlayer,
+            width:500,
+            height:375,
+            params: {flashvars: 'photo_id=' + url.split('/')[5] + '&amp;show_info_box=true' }
+        };
+    }],
+
+    ['youtube.com/watch', function(url){
+        return {
+            //src: 'http://www.youtube.com/embed/'+url.split('v=')[1],
+            url:'http://www.youtube.com/v/'+url.split('v=')[1],
+            width:640, 
+            height:385  //385
+        }
+    }],
+
+    //youtube playlist
+    ['youtube.com/view', function(url){
+        return{
+            url:'http://www.youtube.com/p/'+url.split('p=')[1],
+            width:480,
+            height:385
+        };
+    }],
+
+    ['dailymotion.com',function(url){
+        return {
+            src:'http://www.dailymotion.com/embed/video/'+url.split('/')[4].split('_')[0],
+            //url:url,
+            width:480,
+            height:270 //381
+        }
+    }],
+
+    ['metacafe.com/watch', function(url){
+        //http://www.metacafe.com/watch/<id>/<title>/ => http://www.metacafe.com/fplayer/<id>/<title>.swf
+        return {
+            url:'http://www.metacafe.com/fplayer/' + url.split('/')[4] +'/.swf?playerVars=autoPlay=no',
+            //url:'http://www.metacafe.com/fplayer/' + url.split('watch/')[1].slice(0,-1) +'.swf?playerVars=autoPlay=no',
+            width:400,        //540    600
+            height:350        //304    338
+        }
+    }],
+
+    ['vids.myspace.com', function(url){
+        return {
+            url:url,
+            width:425,        //540    600
+            height:360        //304    338
+        }
+    }],
+
+    ['veoh.com/watch/', function(url){
+        //url: 'http://www.veoh.com/static/swf/webplayer/WebPlayer.swf?version=AFrontend.5.5.2.1001&permalinkId='+url.split('watch/')[1]+'&player=videodetailsembedded&videoAutoPlay=false&id=anonymous',
+        return {
+            url:'http://www.veoh.com/veohplayer.swf?permalinkId='+url.split('watch/')[1]+'&player=videodetailsembedded&videoAutoPlay=false&id=anonymous',
+            width:410,
+            height:341
+        }
+    }],
+
+
+    ['https?://www.ted.com/talks/', function(url){
+    //http://www.ted.com/talks/doris_kim_sung_metal_that_breathes.html
+    //<iframe src="http://embed.ted.com/talks/doris_kim_sung_metal_that_breathes.html" width="560" height="315" frameborder="0" scrolling="no" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
+        return {
+            src:'http://embed.ted.com/talks/'+url.split('/')[4],
+            width:853, //640, //560,
+            height:480, //360, //315
+            scrolling:"no"
+        }
+    }],
+
+    ['viddler.com/', function(url){
+        return {
+            url: url,
+            classid: AdobeFlashPlayer,
+            width: 545, //437,
+            height: 451, //370,
+            params: {id:'viddler_'+url.split('/')[4], movie:url }
+        }
+    }],
+
+    ['http://vimeo.com/', function(url){
+        return {
+            //html5 compatible --- use iframe
+            //src: 'http://player.vimeo.com/video/' + url.split('/')[3],
+            url:'http://www.vimeo.com/moogaloop.swf?server=www.vimeo.com&amp;clip_id='+url.split('/')[3],
+            width:640,
+            height:360
+        }
+    }],
+
+    ['http://jsfiddle.net/',function(url){
+        return {
+            src: url+'embedded/',
+            width:800,
+            height:250
+        }   
+    }],
+
+    ['https?://', function(url){
+        return {
+            //default : catch iframe urls ; allow scrolling of eg external site's
+            src:url
+        }
+    }]
+
+]);
+
+}();