像缩略图一样添加鼠标悬停功能

时间:2018-06-28 09:57:15

标签: javascript jquery ember.js

嗨,我需要通过将鼠标悬停在某个项目(图像,pdf,html等)上来查看该项目的缩略图预览,这样我就可以轻松查看该项目的内容而不必完全加载它。当我将鼠标悬停1秒钟时,它应该在弹出窗口中显示预览,而当我将鼠标悬停在该项目上时,它应该会消失。如果无法在浏览器窗口中显示预览,则显示诸如“无法显示”之类的消息。

为此,我在下面提供了html代码(图标)的pdf预览:

<div id="ember8734" class="ember-view managed-object-tools-icon managed-object-icon-view container-view clickable" style="font-size: 20px">
<rs-icon id="ember8737" class="ember-view primary-icon managed-object-primary-icon icon" style="font-size: 20px">
<icon glyph="type_pdf" class="type_pdf" set="types" style="font-size: 20px;">
</icon>
</rs-icon>
<rs-icon id="ember8743" class="ember-view version-icon icon" style="width: 1em; height: 1em; font-size: 20px">
</rs-icon>
</div>
<managed-object-label id="ember8749" class="ember-view content-data managed-object-label-view managed-object-label-view managed-object-label data-view managed-object-label-view-core_component_data-view-mixin managed-object-label-core_component_data-view-mixin data-view-core_component_data-view-mixin">
<div core-role="primaryLabel" class="" data-bindattr-49="49">story.​pdf</div>

对于所有项目(html,pdf,图像等),缩略图-preview.js代码在此处:

    ScalerMixin = {
        imageWidth: null,
        imageHeight: null,
        containerWidth: null,
        containerHeight: null,
        width: null,
        height: null,
        top: null,
        left: null, 
        attributeBindings: [ 'style', 'src' ],
        style: function () {
            if (!this.get('width') || !this.get('height') || isNaN(this.get('top')) || isNaN(this.get('left'))) {
                return '';
            }
            return 'width: ' + this.get('width') + 'px; height: ' + this.get('height') + 'px; margin-top: ' + this.get('top') + 'px; margin-left: ' + this.get('left') + 'px;';
        }.property('width', 'height', 'top', 'left'),
        captureImageSize: function () {
            if (this.isDestroying || this.isDestroyed) { return; }
            var i = new window.Image();
            i.src = this.get('src');
            this.set('imageWidth', i.width);
            this.set('imageHeight', i.height);
            this.updateSize();
        },
        updateSize: function () {
            if (this.isDestroying || this.isDestroyed) { return; }
            if (!this.imageWidth || !this.imageHeight || !this.containerWidth || !this.containerHeight) {
                return;
            }
            var iar = this.imageWidth / this.imageHeight,
                car = this.containerWidth / this.containerHeight;
            var width, height;
            if (car > iar) {
                height = this.containerHeight;
                width = iar * this.containerHeight;
            } else {
                height = this.containerWidth / iar;
                width = this.containerWidth;
            }
            if (this.width !== width) {
                this.set('width', width);
            }
            if (this.height !== height) {
                this.set('height', height);
            }
            this.set('top', (this.containerHeight - height) / 2);
            this.set('left', (this.containerWidth - width) / 2);
        }.observes('imageWidth', 'imageHeight', 'containerWidth', 'containerHeight'),
        containerWidthBinding: 'parentView.width',
        containerHeightBinding: 'parentView.height',
        _attachLoadHandler: function () {
            this.get('element').onload = this.captureImageSize.bind(this);
        }.on('didInsertElement')
    },

    ThumbnailImage = Ember.View.extend(ScalerMixin, {
        tagName: 'img',         
        isVisible: function () {
            return !!this.get('src');
        }.property('src'),  
        objectBinding: 'parentView.object',
        click: function () {
            alert('thumb1');
            var i = new window.Image(),
                src = this.get('object').uri();
            i.onload = function () {
                Core.openWindow(src, {
                    width: i.width,
                    height: i.height
                });
            };
            i.src = src;
        },
        classNames: [ 'clickable' ]
    }),
    Thumbnail = ThumbnailImage.extend({
        src: function () {
            var object = this.get('object');
            if (!object) { return; }
            var thumb = object.get('keyedVariants.core:thumbnail');
            if (thumb) {
                return object.uri({ variantName: thumb.variantName });
            }
            return null;
        }.property('object', 'object.keyedVariants.core:thumbnail', 'object.variants.length')
    }),
    Image = ThumbnailImage.extend({
        src: function () {
            var object = this.get('object');
            if (!object) { return; }
            var type = object.get('contentType');
            if (/^image\/(?:jpeg|gif|png|svg)/.test(type)) {
                return object.uri();
            }
            return null;
        }.property('object')
    }),             
    Playable = Ember.ContainerView.extend({
        object: null,
        playableSources: function () {
            var playerTag = document.createElement(this.get('playerTagName')),
                sources = this.get('sources') || [];
            return sources.filter(function (source) {
                if (!playerTag.canPlayType) { return false; }
                return !!playerTag.canPlayType(source.type + ';').replace(/no/, '');
            }, this);
        }.property('sources.@each.type'),
        updateSizes: function () {
            var w = Math.min(this.get('parentView.width') | 0),
                h = Math.min(this.get('parentView.height') | 0),
                s = Math.min(128, Math.min(this.get('parentView.width'), this.get('parentView.height')) * 0.75) | 0,
                l = Math.floor((w - s) / 2),
                t = Math.floor((h - s) / 2),
                m = 'margin: ' + t + 'px 0 0 ' + l + 'px';
            this.set('margin', m);
            this.set('iconSize', s);
        }.on('didInsertElement').observes('parentView.width', 'parentView.height'),
        iconSize: 128,
        marginLeft: 0,
        marginTop: 0, 
        PlayView: Ember.ContainerView.extend({
            tagName: null,
            ThumbnailView: ThumbnailImage,
            thumbnailView: childView('ThumbnailView'),
            objectBinding: 'parentView.object',
            attributeBindings: [ 'controls', 'preload', 'style' ],
            style: function () {
                var w = this.get('parentView.parentView.width'),
                    h = this.get('parentView.parentView.height');
                return "max-width: " + w + "px; max-height: " + h + "px;";
            }.property('parentView.parentView.width', 'parentView.parentView.height'),
            controls: "true",
            preload: 'metadata',
            poster: 'thumbnailView.src',
            SourceView: Ember.View.extend({
                tagName: 'source',
                attributeBindings: ['src', 'type'],
                src: null,
                type: null
            }),
            PlayButton: Core.view.Icon.extend({
                classNames: ['play-button'],
                sizeBinding: 'parentView.parentView.iconSize',
                marginBinding: 'parentView.parentView.margin',
                model: 'play',
                click: function () {
                    alert('thumb2');
                    var el = this.get('parentView.element');
                    if (el) {
                        this.get('parentView.element').play();
                    }
                }
            }),
            playButton: childView('PlayButton'),
            sourceViews: function () {
                return this.get('parentView.sources').map(function (source) {
                    return this.createChildView(this.SourceView, source);
                }, this);
            }.property(),
            setupView: function () {
                if (this.isDestroying || this.isDestroyed) { return; }
                this.set('tagName', this.get('parentView.playerTagName'));
                this.replace(0, this.get('length'), []);
                this.get('sourceViews').forEach(function (sourceView) {
                    this.pushObject(sourceView);
                }, this);
                this.pushObject(this.get('thumbnailView'));
                this.pushObject(this.get('playButton'));
            }.on('init').observes('parentView.sources')
        }),
        playView: childView('PlayView'),
        PremediaView: Ember.ContainerView.extend({
            ThumbnailView: ThumbnailImage,
            thumbnailView: childView('ThumbnailView'),
            PlayButton: Core.view.Icon.extend({
                classNames: ['play-button'],
                sizeBinding: 'parentView.parentView.iconSize',
                marginBinding: 'parentView.parentView.margin',
                model: 'play',
                click: function () {
                    alert('thumb3');
                    this.get('parentView.parentView').play();
                }
            }),
            playButton: childView('PlayButton'),
            setupView: function () {
                this.replace(0, this.get('length'), []);
                this.pushObject(this.get('thumbnailView'));
                this.pushObject(this.get('playButton'));
            }.on('init').observes('thumbnailView.src')
        }),
        premediaView: childView('PremediaView'),
        PlaceholderView: Ember.ContainerView.extend({
            ThumbnailView: ThumbnailImage,
            thumbnailView: childView('ThumbnailView'),
            CantPlayButton: Core.view.Icon.extend({
                classNames: ['play-button', 'cant-play'],
                sizeBinding: 'parentView.parentView.iconSize',
                marginBinding: 'parentView.parentView.margin',                  
                model: 'play_not_available',
                titleBinding: 'Core.messageTable.content/icon/preview/cant-play'
            }),
            cantPlayButton: childView('CantPlayButton'),
            setupView: function () {
                this.replace(0, this.get('length'), []);
                this.pushObject(this.get('thumbnailView'));
                this.pushObject(this.get('cantPlayButton'));
            }.on('init').observes('thumbnailView.src')
        }),
        placeholderView: childView('PlaceholderView'),
        media: false,
        play: function () {
            this.set('media', true);
            Ember.run.schedule('render', this, function () {
                var go = function () {
                    var el = this.get('playView.element');
                    if (!el) {
                        Ember.run.later(this, go);
                    } else {
                        $(el).on('canplay', function () {
                            el.play();
                        });
                    }
                }.bind(this);
                go();                   
            });
        },
        setupView: function () {
            this.replace(0, this.get('length'), []);
            if (!this.media) {
                this.pushObject(this.get('premediaView'));
            } else {
                if (this.get('playableSources.length') === 0) {
                    this.pushObject(this.get('placeholderView'));
                } else {
                    this.pushObject(this.get('playView'));
                }
            }
        }.on('init').observes('playableSources.length', 'media')
    });
Core.component.ManagedObjectPreview.MediaPreview = Ember.ContainerView.extend({
    classNames: [ 'thumbnail-preview' ],
    height: 250,
    width: 292,
    captureSizeForRealsies: function () {
        if (this.isDestroying || this.isDestroyed) { return; }
        var el = this.get('element');
        if (!el) {
            Ember.run.later(this, 'captureSizeForRealsies', 125);
            return;
        }
        var rect = el.getBoundingClientRect();
        if (!rect.width || !rect.height) {
            Ember.run.later(this, 'captureSizeForRealsies', 125);
            return; 
        }
        // Find first scrollable containment
        var scrollX = scrollY = el;
        while (scrollX && scrollX.nodeType !== Node.DOCUMENT_NODE && $(scrollX).css('overflow-x') !== 'auto') {
            scrollX = scrollX.parentNode;
        }
        while (scrollY && scrollY.nodeType !== Node.DOCUMENT_NODE && $(scrollY).css('overflow-y') !== 'auto') {
            scrollY = scrollY.parentNode;
        }
        if (scrollY) {
            rect.height = Math.min(rect.height, scrollY.clientHeight);
        }
        if (scrollX) {
            rect.width = Math.min(rect.width, scrollX.clientWidth);
        }
        this.beginPropertyChanges();
        if (rect.width !== this.width) {
            this.set('width', rect.width);
        }
        if (rect.height !== this.height) {
            this.set('height', rect.height);
        }
        this.endPropertyChanges();
    },
    captureSize: function () {
        Ember.run.later(this, 'captureSizeForRealsies', 125);
    }.on('didInsertElement').observes('Core.document.width'),
    classNameBindings: [ 'isImage:ui-clickable' ],
    objectBinding: 'model.finalManagedObject',
    thumb: Ember.computed(function () {
        var uri, mo = this.get('object');
        if (!mo) { return; }
        if (mo.getVariant('core:thumbnail')) {
            uri = Core.restUrl(2, 'content/binary/id/' + this.get('object.id') + '?variant=core:thumbnail');
            if (mo.get('revision')) {
                uri += '&revision=' + mo.get('revision');
            }
            return uri;
        }
        return null;
    }).property(
        'object.variants.@each.variantName',
        'object.id',
        'object.revision'
    ),
    isImage: function () {
        var contentType = this.get('object.contentType'),
            isImage = (/^image\/(?:jpeg|gif|png|svg)/).test(contentType);
        return isImage;
    }.property('object.contentType'),
    urlsFor: function (type) {
        var obj = this.get('object') || this.get('model');
        URL = obj.streamingUri;
        var parentId = $('.preview-and-information-view').attr('id');
        var childId = $('#' + parentId).find('div').attr('id');
        if (obj.contentType == 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
            $('#'+childId).html('<a href="'+URL+'" target=_blank><span style=cursor:pointer><img src=/core-cms/plugin/core-cms-theme/images/core/content-type/24/office-powerpoint.png  alt=power-point style=width: 20px; cursor:pointer;></span></a>');
            return false;
        }
        else if(obj.contentType == 'text/plain' || obj.contentType == 'application/vnd.ms-xpsdocument'){
            $('#'+childId).html('<a href="'+URL+'" target=_blank><span style=cursor:pointer><img src=/core-cms/plugin/core-cms-theme/images/core/content-type/24/file-generic.png style=width: 20px;cursor:pointer;></span></a>');
            return false;
        }
        else if(obj.contentType == 'application/pdf'){
            $('#'+childId).html('<a href="'+URL+'" target=_blank ><span style=cursor:pointer><icon glyph=type_pdf class=type_pdf set=types style=font-size:20px;cursor:pointer;></icon></span></a>');
            return false;
        }
        else if(obj.contentType == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'){
            $('#'+childId).html('<a href="'+URL+'" target=_blank ><span style=cursor:pointer><img src=/core-cms/plugin/core-cms-theme/images/core/content-type/24/office-word.png alt=office-word style=width: 20px;cursor:pointer;></span></a>');
            return false;
        }
        else if(obj.contentType == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'){
            $('#'+childId).html('<a href="'+URL+'" target=_blank ><span style=cursor:pointer><img src=/core-cms/plugin/core-cms-theme/images/core/content-type/24/office-excel.png style=width: 20px;cursor:pointer;></span></a>');
            return false;
        }
        else if(obj.contentType == 'application/x-shockwave-flash'){
            $('#'+childId).html('<a href="'+URL+'" target=_blank ><span style=cursor:pointer><icon glyph=type_adobe_flash_ class=type_adobe_flash set=types style=font-size: 20px;cursor:pointer;></icon></span></a>');
            return false;
        }
        else {
            $('#'+childId).html('');
        }
        if (!obj) { return; }
        var items = [obj].concat(obj.get('variants') || []);
        items = items.map(function (variant) {
            var ret = {};
            if (Ember.get(variant, 'variantName')) {
                ret.src = obj.uri({ variantName: Ember.get(variant, 'variantName') });
            } else {
                ret.src = obj.uri();
            }
            ret.type = Ember.get(variant, 'contentType');
            return ret;
        });
        items = items.filter(function (item) {
            if (!item.src || !item.type) { return false; }
            return item.type.substr(0, type.length + 1) === (type + '/');
        });
        return items;
    },
    videoUrls: function () {
        return this.urlsFor('video');
    }.property('object.contentType', 'object.variants.@each.contentType'),
    isVideo: function () {
        return !!this.get('videoUrls.length');
    }.property('videoUrls.length'),
    audioUrls: function () {
        return this.urlsFor('audio');
    }.property('object.contentType', 'object.variants.@each.contentType'),
    isAudio: function () {
        return !!this.get('audioUrls.length');
    }.property('audioUrls.length'),
    objectChanged: function () {
        console.log(this);
        if (this.get('length')) {
            this.replace(0, this.get('length'), []);
        }
        if (this.get('isVideo')) {
            this.pushObject(this.get('videoView'));
        } else if (this.get('isAudio')) {
            this.pushObject(this.get('audioView'));
        } else {
            this.pushObject(this.get('imageView'));
        }
    }.on('init').observes('object', 'media'),
    VideoView: Playable.extend({
        classNames: [ 'video-preview' ],
        playerTagName: 'video',
        objectBinding: 'parentView.object',
        sourcesBinding: 'parentView.videoUrls'
    }),
    videoView: childView('VideoView'),
    AudioView: Playable.extend({
        classNames: [ 'audio-preview' ],
        playerTagName: 'audio',
        objectBinding: 'parentView.object',
        sourcesBinding: 'parentView.audioUrls'
    }),
    audioView: childView('AudioView'),
    ImageView: Image.extend({
        classNames: [ 'image-preview' ]
    }),
    imageView: childView('ImageView'),
    ThumbView: Thumbnail.extend({
        classNames: [ 'thumbnail-preview' ]
    }),
    thumbView: childView('ThumbView')
});
Core.component.ManagedObjectPreview.ThumbPreview = Core.component.ManagedObjectPreview.MediaPreview.extend({
    objectChanged: function () {
        if (this.get('length')) {
            this.replace(0, this.get('length'), []);
        }
        if (this.get('thumb')) {
            this.pushObject(this.get('thumbView'));
        }       
    }.on('init').observes('object')
});
var LocalNavigator = Core.component.NavigableSection.Navigator.extend({
    objectBinding: 'sectionView.model.finalManagedObject',
    tooltipBinding: "Core.messageTable.content/preview/thumbnail",
    enabled:function () {
        return !!this.get('types.length');
    }.property('types', 'types.length')
});
Core.component.ManagedObjectPreview.proto().navigators.pushObjects([
    LocalNavigator.extend({
        enabled: function () {
            return !!this.get('types.length');
        }.property('types.length'),
        icon: function () {
            if (this.get('thumb')) {
                return 'thumbnail_missing';
            }
            var types = this.get('types'),
                isAudio = false,
                isVideo = false;
            types.forEach(function (type) {
                if (/^video\//.test(type)) {
                    isVideo = true;
                }
                if (/^audio\//.test(type)) {
                    isAudio = true;
                }
                if (/^application\//.test(type)) {
                    isDocument = true;
                }
            });
            if (isVideo) {
                return 'types:type_video';
            }
            if (isAudio) {
                return 'types:type_audio';
            }
            return types.find(function (type) {
                return /^image\//.test(type);
            }) ? 'types:type_image' : 'thumbnail_missing';
        }.property('thumb', 'object'),
        thumb: function () {
            var obj = this.get('object'),
                variants = obj && obj.get('variants'),
                types;
            if (!variants) { return null; }
            return obj && obj.get('keyedVariants.core:thumbnail');
        }.property('object.keyedVariants.core:thumbnail'),
        types: function () {
            var thumb = this.get('thumb');
            if (thumb) {
                return [ thumb.contentType ];
            }
            var obj = this.get('object'),
                variants = (obj && obj.get('variants')) || [],
                types;
            if (!obj) { return []; }
            types = [ obj.get('contentType') ];
            variants.forEach(function (variant) {
                if (variant.variantName !== 'core:thumbnail') {
                    types.push(variant.contentType);
                }
            });
            types = types.filter(function (type) {
                return (/^(image|audio|video|application)\//).test(type);
            });
            return types;       
        }.property('object', 'object.keyedVariants', 'object.variants.length'),
    }).create()
]);

对于在ManagedObjecttool.js中具有代码的相应图标:

ObjectIconView: Ember.ContainerView.extend(childMOMixin, {
                classNames: ['managed-object-tools-icon'],
                classNameBindings: [ 'clickable' ],
                attributeBindings: [ 'style' ],
                style: function () {
                    return 'font-size: ' + this.get('size') + 'px';
                }.property('size'),
                mouseDown: function () { return false; },
                click: function () {
                    var actionMenuContext = this.get('actionMenuContext'),
                        element = this.$(),
                        row = element.parents('tr:first'),
                        ctl = this.get('controller');
                    if (ctl && ctl.send) {
                        ctl.send('contentItemActionMenu', row.length ? row : element, element, actionMenuContext);
                    }
                    return false;
                },
                clickable: function () {
                    return !!this.get('controller._actions.contentItemActionMenu');
                }.property(''),
                childViews: [
                    'PrimaryIcon',
                    'TypeOverlay',
                    'VersionStatus',
                    'DraftStatus'
                ],
                size: 20,
                PrimaryIcon: Core.component.ManagedObjectPrimaryIcon.extend(childMOMixin, {
                    sizeBinding: 'parentView.size',
                    loadStateBinding: 'parentView.loadState',
                    suggestedIconsBinding: 'parentView.suggestedIcons'
                }),
                VersionStatus: Core.view.Icon.extend(childMOMixin, {
                    sizeBinding: 'parentView.size',
                    classNames: ['version-icon'],
                    classNameBindings: [ 'model' ],
                    model: function () {
                        if (this.get('isFrozen')) { return 'status_pinned'; }
                        if (this.get('isOwned')) { return 'status_checked_out'; }
                        if (this.get('isLocked')) { return 'status_locked'; }
                    }.property('isFrozen', 'isOwned', 'isLocked')
                }),
                DraftStatus: Core.view.Icon.extend(childMOMixin, {
                    sizeBinding: 'parentView.size',
                    classNames: ['version-icon'],
                    classNameBindings: [ 'model' ],
                    model: function () {
                        if (this.get('hasDraft')) { return 'status_draft'; }
                        return "$blank";
                    }.property('hasDraft')
                }),
                TypeOverlay: Core.view.Icon.extend(childMOMixin, {
                    sizeBinding: 'parentView.size',
                    classNames: ['type-icon'],
                    classNameBindings: [ 'model' ],
                    model: function () {
                        var type = this.get('finalObjectType');
                        if (type === 'canode') {
                            return 'status_ca_node';
                        }
                        if (type === 'mo') {
                            return 'status_is_xml';
                        }
                        //if (type === 'mononxml' && this.get('variants.length') > 0) {
                        //  return 'status_has_variants';
                        //}
                        return '$blank';
                    }.property('parentView.finalMO.objectType', 'finalObjectType')
                })
            }).named("ManagedObjectIconView")

我尝试使用“ mouseMove”选项。但是图像没有显示。请为此提供建议。我是炭烬新手。如果您需要更多详细信息,请在评论中问我。您的帮助将不胜感激。预先感谢。

1 个答案:

答案 0 :(得分:0)

如果您在组件的旁边,请使用以下命令:

如果图像位于弹出框上:

window

或者您可以使用鼠标悬停来触发图像。例如:

mouseEnter(){
   this.$().popover( 'show' );
},

mouseLeave(){
  this.$().popover( 'hide' );
}