javascripthtmljquerycssapi-linkpreview

Minipreview jQuery link preview contents of parent <p> or <div> only


I'd like to use https://github.com/lonekorean/mini-preview to create mouseover previews for parts of a website only.

I have no problems using anchors from the target website to have the script render a full website preview, scrolled to where an individual anchor is. That's not what I'm after however.

I'd like the script to show only the content of the anchors' parent <p> or <div>.

On the site, the link target anchors are coded like this:

<div class="paragraph">
    <p>
        <a id="anchor_1"></a>
        Foo bar baz.
    </p>
</div>

So, I'd like the little preview box to show Foo bar baz. only.

I suspect the answer lies in this part of the script:

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');
});

specifically, the .attr('src', this.$el.attr('href')) part. I'm not sure though.

Does anyone know how I can do this?
Or can you recommend some other script that I can use to do this and makes things look as nice as this one?

I'm not a web dev, so please go easy on me.
Thanks

UPDATE (based on Swati's answer and corresponding comments):

For example, if my website includes this:

<body>
    <p>
        <a href="#anchor_on_my_site">See internal</a>
    </p>
    <p>
        <a href="external_website.html#external_anchor">See external</a>
    </p>
    <div class="paragraph">
        <p>
            <a id="anchor_on_my_site"></a>
                Foo bar baz.
        </p>
    </div>
</body>

and the external website includes this:

<body>
    <div class="paragraph">
        <p>
            <a id="external_anchor"></a>
                Qux quux quuz.
        </p>
    </div>
</body>

I'd like See internal to display Foo bar baz. and See external to display Qux quux quuz.


Solution

  • Inside loadPreview function you can use closest('p').clone().children().remove().end().text() to get text from p tag where a has been hover then using this put that text to show inside your frame div i.e : .find('.' + PREFIX + '-frame').text(data_to_show) .

    Demo Code :

    (function($) {
      var PREFIX = 'mini-preview';
    
      $.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: 'parenthover'
        },
    
        generate: function() {
          this.createElements();
          this.setPrefetch();
        },
    
        createElements: function() {
          var $wrapper = $('<div>', {
            class: PREFIX + '-wrapper'
          });
          //no need to use iframe...use simple div 
          var $frame = $('<div>', {
            class: PREFIX + '-frame'
          });
          var $cover = $('<div>', {
            class: PREFIX + '-cover'
          });
          $wrapper.appendTo(this.$el).append($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 + ')'
          });
          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;
          //add more style here ...if needed to outer div
          $wrapper.css({
            top: top + 'px',
            left: left + 'px',
            'font-size': '55px',
            'color': 'blue'
          });
        },
    
        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() {
          //to get text from p tag
          var data_to_show = this.$el.closest('p').clone().children().remove().end().text().trim()
          //set new text inside div frame
          this.$el.find('.' + PREFIX + '-frame').text(data_to_show)
          //set bg color..
          this.$el.find('.' + PREFIX + '-frame').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);
    
    
    $('a').miniPreview();
    body {
      height: 100%;
      margin: 0;
      padding: 0 10% 40px;
      font-size: 2rem;
      line-height: 1.5;
      font-family: 'Roboto Slab', sans-serif;
      text-align: justify;
      color: #59513f;
      background-color: #f5ead4;
    }
    
    a {
      color: #537f7c;
    }
    
    .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-cover {
      background-color: rgba(0, 0, 0, 0);
      /* IE fix */
    }
    
    .mini-preview-frame {
      border: none;
      -webkit-transform-origin: 0 0;
      transform-origin: 0 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <html>
    
    <body>
      <div class="paragraph">
        <p>
          <a id="anchor_1">See</a> This is text we are showing for first
        </p>
        <p>
          <a id="anchor_2">See</a> This is text we are showing for second
        </p>
      </div>
    </body>
    
    </html>

    Update 1 :

    You can differentiate between external & internal link using some class i.e : simply check if the a tag which is hover has a particular class or not depending on this change your code to preview divs.

    Updated Code :

    if (this.$el.hasClass("internal")) {
            //to get text from p tag
            var data_to_show = this.$el.closest('p').siblings(".paragraph").clone().text().trim()
            //set new text inside div frame
            this.$el.find('.' + PREFIX + '-frame').text(data_to_show)
            //set bg color..
            this.$el.find('.' + PREFIX + '-frame').css('background-color', '#fff');
    } else {       
            console.log("for external code ..")    
    }