News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Mini-preview when hovering over post link

Started by drewactual, January 12, 2019, 07:54:58 PM

Previous topic - Next topic

drewactual

big thanks to Mr. Will Boyd for the original script offered up here.

another thread was looking for something like this.  this works but will benefit from some refinement.  right now, here are some issues with this:

  • even using the prefetch:none call, once a link is brought in using this function the padlock will break if that page isn't secure.
  • in it's present form, the script doesn't ignore links to the same page
  • the script needs to be refined so as not to render page 'jerky'.

as mention in the code, here is how it's done:

  • create a file.. call it what you may, let's call it 'whatever.js' for the moment and as an example.
  • copy the js code found below in that file.
  • change the external js call line to the address you plopped the js file and name.
  • save.
  • the first part of the code below, this needs to be stripped and pasted in your index.template, preferably 'under the fold'.
  • notice in that snippet i used a div class called 'hubber' as the area this function will work.
  • open your display.template and find the line that starts with (commented out) "finally, the post" or something to that impact.
  • on the 'echo line, and between .post and .inner opening, add an opening tag for hubber (or whatever you call it).
  • add another div close tag after the 'post' function.. there will be three there now instead of two.


here it is:

add this to your index.template 'under the fold', which is to say just above the </html> line.

echo '
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<link href="./jquery.minipreview.css" rel="stylesheet">
<script src="./jquery.minipreview.js"></script>
<script type="text/javascript"> $(function() { $(\'.hubber a\').miniPreview({ prefetch: \'none\' });
            });
</script>
<script src="xxxxxx-link to location and file you saved the below js-xxxxxx"></script>
';


make an external file, and save it with this-


/*
* MiniPreview v0.9
* @author  Will Boyd
* Shared by Codegena
*/

(function($) {
    var PREFIX = 'mini-preview';
    // implemented as a jQuery plugin
    $.fn.miniPreview = function(options) {
        return this.each(function() {
            var $this = $(this);
            var miniPreview = $this.data(PREFIX);
            if (miniPreview) {
                miniPreview.destroy();
            }
            miniPreview = new MiniPreview($this, options);
            miniPreview.generate();
            $this.data(PREFIX, miniPreview);
        });
    };
    var MiniPreview = function($el, options) {
        this.$el = $el;
        this.$el.addClass(PREFIX + '-anchor');
        this.options = $.extend({}, this.defaultOptions, options);
        this.counter = MiniPreview.prototype.sharedCounter++;
    };
    MiniPreview.prototype = {
        sharedCounter: 0,
        defaultOptions: {
            width: 256,
            height: 144,
            scale: .25,
            prefetch: 'pageload'
        },
        generate: function() {
            this.createElements();
            this.setPrefetch();
        },
        createElements: function() {
            var $wrapper = $('<div>', { class: PREFIX + '-wrapper' });
            var $loading = $('<div>', { class: PREFIX + '-loading' });
            var $frame = $('<iframe>', { class: PREFIX + '-frame' });
            var $cover = $('<div>', { class: PREFIX + '-cover' });
            $wrapper.appendTo(this.$el).append($loading, $frame, $cover);
            // sizing
            $wrapper.css({
                width: this.options.width + 'px',
                height: this.options.height + 'px'
            });
            // scaling
            var inversePercent = 100 / this.options.scale;
            $frame.css({
                width: inversePercent + '%',
                height: inversePercent + '%',
                transform: 'scale(' + this.options.scale + ')'
            });
            // positioning
            var fontSize = parseInt(this.$el.css('font-size').replace('px', ''), 10)
            var top = (this.$el.height() + fontSize) / 2;
            var left = (this.$el.width() - $wrapper.outerWidth()) / 2;
            $wrapper.css({
                top: top + 'px',
                left: left + 'px'
            });
        },
        setPrefetch: function() {
            switch (this.options.prefetch) {
                case 'pageload':
                    this.loadPreview();
                    break;
                case 'parenthover':
                    this.$el.parent().one(this.getNamespacedEvent('mouseenter'),
                        this.loadPreview.bind(this));
                    break;
                case 'none':
                    this.$el.one(this.getNamespacedEvent('mouseenter'),
                        this.loadPreview.bind(this));
                    break;
                default:
                    throw 'Prefetch setting not recognized: ' + this.options.prefetch;
                    break;
            }
        },
        loadPreview: function() {
            this.$el.find('.' + PREFIX + '-frame')
                .attr('src', this.$el.attr('href'))
                .on('load', function() {
                    // some sites don't set their background color
                    $(this).css('background-color', '#fff');
                });
        },
        getNamespacedEvent: function(event) {
            return event + '.' + PREFIX + '_' + this.counter;
        },
        destroy: function() {
            this.$el.removeClass(PREFIX + '-anchor');
            this.$el.parent().off(this.getNamespacedEvent('mouseenter'));
            this.$el.off(this.getNamespacedEvent('mouseenter'));
            this.$el.find('.' + PREFIX + '-wrapper').remove();
        }
    };
})(jQuery);


and the css:
.mini-preview-anchor {
    display: inline-block;
    position: relative;
    white-space: nowrap;
}

.mini-preview-wrapper {
    -moz-box-sizing: content-box;
    box-sizing: content-box;
    position: absolute;
    overflow: hidden;
    z-index: -1;
    opacity: 0;
    margin-top: -4px;
    border: solid 1px #000;
    box-shadow: 4px 4px 6px rgba(0, 0, 0, .3);
    transition: z-index steps(1) .3s, opacity .3s, margin-top .3s;
}

.mini-preview-anchor:hover .mini-preview-wrapper {
    z-index: 2;
    opacity: 1;
    margin-top: 6px;
    transition: opacity .3s, margin-top .3s;
}

.mini-preview-loading, .mini-preview-cover {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;   
}

.mini-preview-loading {
    display: table;
    height: 100%;
    width: 100%;
    font-size: 1.25rem;
    text-align: center;
    color: #f5ead4;
    background-color: #59513f;
}

.mini-preview-loading::before {
    content: 'Loading...';
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}

.mini-preview-cover {
    background-color: rgba(0, 0, 0, 0); /* IE fix */
}

.mini-preview-frame {
    border: none;
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
}


that should be enough to get you off and running.  Some tweaking by someone who wants to use it, and it'll work out well.

Steve

I can't decide if this should be a 'Tip and Trick' or a mod ...
DO NOT pm me for support!

drewactual

Thats up to you guys who, the experts!  Its simple enough to implement and remove, like a mod, but requires some effort in the backend that a mod doesn't. Maybe someone will make it such?  I dont know.,,,. I was playing with it Friday night and Saturday morning as a tool with intnet to credit sources posted on my site, but it doesnt "flow" right for me and the juice isnt worth the squeeze to fix it where it will, at least for my purposes...

Someone here May find use for it, though.

Advertisement: