- // ==UserScript==
- // @name MiniblogImgPop - 微博浮图
- // @namespace http://userscripts.org/users/83994
- // @icon https://addons.cdn.mozilla.net/img/uploads/addon_icons/337/337281-64.png?modified=1361080128
- // @description 微博浮图控件,鼠标移过小图弹出浮动大图的脚本
- // @version 3.4.2
- // @include http://*qing.weibo.com/*
- // @include http://*weibo.com/*
- // @include https://*weibo.com/*
- // @include http://*t.163.com/*
- // @include http://*t.sohu.com/*
- // @include http://*t.qq.com/*
- // @include http://*t.ifeng.com/*
- // @include http://*t.titan24.com/*
- // @include http://*t.people.com.cn/*
- // @include http://*tianya.cn/*
- // @include http://*diandian.com/*
- // @include http://*.digu.com/*
- // @include http://i.taobao.com/*
- // @include http://*t.cntv.cn*
- // @include *://*tieba.baidu.com/f*
- // @include http://*tieba.baidu.com/i*
- // @include http://*xueqiu.com/*
- // @include https://*douban.com/*
- // @include https://*work.alibaba-inc.com/*
- // @grant none
- // ==/UserScript==
-
- // @author afc163
- // @weibo http://weibo.com/afc163
- // @code https://github.com/afc163/MiniblogImgPop
- // @blog http://pianyou.me
- // @date 2010.8.12
-
- (function() {
-
- // 各微博站点的feed配置
- var MIPConfig = {
- 'qing.weibo.com':{
- feedSelector:'.imgZoomIn',
- sFrag :'',
- bFrag :''
- },
- 'q.weibo.com':{
- feedSelector:'.bigcursor',
- sFrag :'thumbnail',
- bFrag :'large'
- },
- 'weibo.com':{
- feedSelector:'.bigcursor, .feed_img, .media_list img',
- sFrag :['thumb180', 'thumb150', 'orj480', 'orj360', 'thumbnail', 'square'],
- bFrag :['mw690', 'mw690', 'mw690', 'mw690', 'bmiddle', 'bmiddle']
- },
- 't.sohu.com':{
- feedSelector:'.pic',
- sFrag :['/f_','_1.jpg'],
- bFrag :['/m_','_0.jpg']
- },
- 't.163.com':{
- feedSelector:'.tweet-preview-pic',
- sFrag :['w=140&h=140', '&gif=1'],
- bFrag :['w=440', '&gif=0']
- },
- 't.qq.com':{
- feedSelector:'.pic img:not(.large)',
- sFrag :['/160', '/120'],
- bFrag :['/460', '/460']
- },
- 't.titan24.com':{
- feedSelector:'.imgBig',
- sFrag :'_thumbnail',
- bFrag :'_middle'
- },
- 't.people.com.cn':{
- feedSelector:'.list_s_pic img',
- sFrag:'/s_',
- bFrag:'/b_'
- },
- 't.ifeng.com':{
- feedSelector:'.zoom_in_image img',
- sFrag :'/128x160_',
- bFrag :'/520x0_'
- },
- 'www.tianya.cn':{
- feedSelector:'.pic-zoomin',
- bigSrc :'_middlepic',
- sFrag :'small',
- bFrag :'middle'
- },
- 'diandian.com':{
- feedSelector:'.feed-img',
- bigSrc :'imgsrc'
- },
- 'digu.com':{
- feedSelector:'.picture',
- sFrag :'_100x75',
- bFrag :'_640x480'
- },
- 't.cntv.cn':{
- feedSelector:'.zoom-move',
- sFrag :'/thumbnail',
- bFrag :'/bmiddle'
- },
- 'i.taobao.com':{
- feedSelector:'.thumb-image',
- sFrag :'_160x160',
- bFrag :'_450x10000'
- },
- 'tieba.baidu.com/f':{
- feedSelector:'.threadlist_media li',
- bigSrc: 'bpic'
- },
- 'tieba.baidu.com/i':{
- feedSelector:'.feat_img',
- bigSrc: 'data-field'
- },
- 'xueqiu.com':{
- feedSelector:'.expandable > img',
- sFrag :'!thumb',
- bFrag :'!custom'
- },
- 'douban.com':{
- feedSelector:'img',
- sFrag :'median',
- bFrag :'raw'
- },
- 'work.alibaba-inc.com':{
- feedSelector:'.uxcore-nw-message-wall-item-album-thumb li',
- sFrag :['240x240', '120x120'],
- bFrag :['620x10000', '620x10000']
- }
- };
-
- // 居中显示的图片对象
- var PopImg = {
-
- show: function(e) {
- this.allowMove = false;
- // fix firefox 22 beta 1
- this._hideTimer && window.clearTimeout(this._hideTimer);
-
- var that = this;
- var smallImg = MiniblogImgPop.smallImg;
- var src = this.getBigImgsrc(smallImg);
- this.img.src = src;
- this.imgWidth = 500;
-
- imgReady(src, function() {
- that.imgWidth = this.width;
- that.layoutImg(e);
-
- that.img.style.opacity = 1;
- that.img.style.visibility = 'visible';
- that.img.style.marginTop = '-15px';
- Mask.show(e);
-
- // 换算图片显示高度
- // 1. 宽度超过 500 时,高度要等比例压缩
- // 2. 加上边框高度
- var imgDisplayHeight;
- if (this.width > 500) {
- imgDisplayHeight = (this.height + 14) * 500 / this.width;
- } else {
- imgDisplayHeight = this.height + 14;
- }
-
- if (window.innerHeight > imgDisplayHeight) {
- var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
- that.img.style.top = (scrollTop + (window.innerHeight - imgDisplayHeight)/2 + 15) + 'px';
- that.allowMove = false;
- } else {
- that.allowMove = true;
- that.move(e);
- }
- });
- },
-
- // 设置大图的宽度与位置
- layoutImg: function(e) {
- var pos = offset(MiniblogImgPop.smallImg);
- var left = pos.x + pos.width + 30;
- var width = Math.min(this.imgWidth, 500);
- // 如果小图右边放不下
- if (left + width > window.innerWidth) {
- left = pos.x - width - 30;
- // 如果左边也放不下
- if (left < 0) {
- // 根据鼠标位置,选择空间大的一侧放置
- if (e.pageX > window.innerWidth / 2) {
- // 放置在左边
- width = Math.min(width, e.pageX - 30);
- left = 0;
- } else {
- // 放置在右边
- width = Math.min(width, window.innerWidth - e.pageX - 30);
- left = window.innerWidth - width;
- }
- }
- }
- this.img.style.width = width + 'px';
- this.img.style.left = left + 'px';
- },
-
- hide: function() {
- var that = this;
- this.img.style.opacity = 0;
- this.img.style.marginTop = '0px';
-
- Mask.hide();
- this.shown = false;
-
- this._hideTimer = window.setTimeout(function() {
- that.img.src = '';
- that.img.style.visibility = 'hidden';
- }, 200);
- },
-
- init: function() {
- var node = document.createElement('img');
- node.id = 'miniblogImgPop';
- document.body.appendChild(node);
- this.img = node;
-
- Mask.init();
- },
-
- move: function(e) {
- this.layoutImg(e); // 重新计算大图宽度与位置
- if (!this.allowMove) {
- return;
- }
- Mask.move(e);
- // 根据 Mask 的位置算出大图的位置
- var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
- this.img.style.top = (scrollTop - Mask.top * Mask.scale) + 14 + 'px';
- },
-
- getBigImgsrc: function(obj) {
- var tempimgs, tempimg, imgsrc, i, l,
- sname = MiniblogImgPop.sitename,
- config = MiniblogImgPop.config;
- if (obj.tagName === 'IMG' || obj.tagName === 'img') {
- tempimg = obj;
- } else {
- tempimgs = obj.getElementsByTagName('IMG');
- if (!tempimgs || tempimgs.length === 0) {
- throw 'cant found the img node.';
- }
- else{
- tempimg = tempimgs[0];
- }
- }
-
- //针对使用额外属性保存大图地址的网站
- if (config.bigSrc) {
- return tempimg.getAttribute(config.bigSrc) || 'javascript:;';
- }
-
- //一般处理
- imgsrc = tempimg.getAttribute('src');
- //console.info(imgsrc);
- imgsrc = decodeURIComponent(imgsrc);
- if (typeof config.sFrag === 'object') {
- for(i=0, l=config.sFrag.length; i<l; i++) {
- imgsrc = imgsrc.replace(config.sFrag[i], config.bFrag[i]);
- }
- }
- else{
- imgsrc = imgsrc.replace(config.sFrag, config.bFrag);
- }
- return imgsrc;
- }
-
- };
-
- // 图片上遮罩的阴影
- var Mask = {
- show: function(e) {
- var smallImg = MiniblogImgPop.smallImg,
- bigImg = PopImg.img;
-
- this.sOffset = offset(smallImg);
-
- // 表示放大的倍数
- this.scale = (bigImg.height + 14) * 1.0 / this.sOffset.height;
-
- // 计算出bar的高度
- if (window.innerHeight < bigImg.height) {
- this.height = parseInt(window.innerHeight/this.scale, 10);
- } else {
- this.height = this.sOffset.height;
- }
-
- // 计算bar的Top值可以允许的范围
- this.range = this.sOffset.height - this.height;
-
- // 计算 mask 的位置
- this.nodes[0].style.left = this.sOffset.x + 'px';
- this.nodes[0].style.width = this.sOffset.width + 'px';
- this.nodes[0].style.top = this.sOffset.y + 'px';
- this.nodes[1].style.left = this.sOffset.x + 'px';
- this.nodes[1].style.width = this.sOffset.width + 'px';
- this.nodes[1].style.bottom = (window.innerHeight - this.sOffset.y - this.sOffset.height) + 'px';
- this.move(e);
-
- this.nodes[0].style.opacity = 0.7;
- this.nodes[1].style.opacity = 0.7;
- },
- hide: function() {
- this.nodes[0].style.opacity = 0;
- this.nodes[1].style.opacity = 0;
- this.nodes[0].style.height = 0;
- this.nodes[1].style.height = 0;
- },
- move: function(e) {
- // 计算鼠标相对于元素的位置
- var x = e.pageX - this.sOffset.x,
- y = e.pageY - this.sOffset.y;
-
- // 计算bar的top值
- var top = y - this.height/2;
- top = top < 0 ? 0 : top;
- top = top > this.range ? this.range : top;
- this.top = top;
-
- this.nodes[0].style.height = top + 'px';
- this.nodes[1].style.height = (this.sOffset.height - top - this.height) + 'px';
- },
- init: function() {
- var node1 = document.createElement('div');
- node1.className = 'miniblogImgPop-mask';
- document.body.appendChild(node1);
- var node2 = document.createElement('div');
- node2.className = 'miniblogImgPop-mask';
- document.body.appendChild(node2);
- this.nodes = [node1, node2];
- }
- };
-
- var MiniblogImgPop = {
-
- preloadImg: function() {
- var that = this;
- window.setTimeout(function() {
- var nodes = $(that.config.feedSelector);
- for (var i=0; i<nodes.length; i++) {
- var preloadImg = new Image();
- preloadImg.src = PopImg.getBigImgsrc(nodes[i]);
- }
- }, 1500);
- },
-
- prepare: function() {
- this.sitename = this._getSiteName();
- this.config = MIPConfig[this.sitename];
- },
-
- addImgsEventListener: function() {
- var that = this;
- delegate(document.body, 'mouseover', function(e, node) {
- that.smallImg = node;
- node.style.opacity = 0.84;
- PopImg.show(e);
- }, this.config.feedSelector);
- delegate(document.body, 'mouseout', function(e, node) {
- node.style.opacity = '';
- PopImg.hide();
- }, this.config.feedSelector);
- delegate(document.body, 'mousemove', function(e) {
- PopImg.move(e);
- }, this.config.feedSelector);
- },
-
- // 获得当前站点名
- _getSiteName: function() {
- var i, each;
- for(each in MIPConfig) {
- if (location.href.indexOf(each) != -1) {
- return each;
- }
- }
- return '';
- },
-
- init: function() {
- // 初始化两个节点
- PopImg.init();
- // 准备必要的数据
- this.prepare();
- // 绑定imgs hover事件
- this.addImgsEventListener();
- // 预加载大图
- this.preloadImg();
- }
-
- };
-
- // 启动
- MiniblogImgPop.init();
-
-
- // Helpers
- // ---
-
- function $(selector) {
- return document.querySelectorAll(selector);
- }
-
- function offset(source) {
- var pt = {
- x:0,
- y:0,
- width:source.offsetWidth,
- height:source.offsetHeight
- };
- do {
- pt.x += source.offsetLeft;
- pt.y += source.offsetTop;
- source = source.offsetParent;
- } while (source);
- return pt;
- }
-
- function delegate(el, eventType, handler, selector) {
- el = el || document;
- el.addEventListener(eventType, function(e) {
- var node = getHandlerNode(e, selector, el);
- node && handler.call(el, e, node);
- }, false);
-
- function getHandlerNode(e, selector, el) {
- //返回我们handler需要的参数
- var nodes;
- el = el || document;
- if (e && e.target && selector) {
- nodes = el.querySelectorAll(selector);
- for(i=0; i<nodes.length; i++) {
- if (e.target == nodes[i] || isInDomChain(e.target, nodes[i], el)) {
- return nodes[i];
- }
- }
- return false;
- }
- }
-
- function isInDomChain(target, parent, ancestor, maxDepth) {
- ancestor = ancestor || null;
- maxDepth = maxDepth || 100;
-
- if (target == ancestor) {
- return false;
- }
- if (target == parent) {
- return true;
- }
- var i = 0;//防止过多嵌套
- while (target != ancestor && target !== null && (i++ < maxDepth)) {
- target = target.parentNode;
- if (target == parent) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * 图片头数据加载就绪事件 - 更快获取图片尺寸
- * @version 2011.05.27
- * @author TangBin
- * @see http://www.planeart.cn/?p=1121
- * @param {String} 图片路径
- * @param {Function} 尺寸就绪
- * @param {Function} 加载完毕 (可选)
- * @param {Function} 加载错误 (可选)
- * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
- alert('size ready: width=' + this.width + '; height=' + this.height);
- });
- */
- var imgReady = (function () {
- var list = [], intervalId = null,
-
- // 用来执行队列
- tick = function () {
- var i = 0;
- for (; i < list.length; i++) {
- list[i].end ? list.splice(i--, 1) : list[i]();
- }
- !list.length && stop();
- },
-
- // 停止所有定时器队列
- stop = function () {
- window.clearInterval(intervalId);
- intervalId = null;
- };
-
- return function (url, ready, load, error) {
- var onready, width, height, newWidth, newHeight,
- img = new Image();
-
- img.src = url;
-
- // 如果图片被缓存,则直接返回缓存数据
- if (img.complete) {
- ready.call(img);
- load && load.call(img);
- return;
- }
-
- width = img.width;
- height = img.height;
-
- // 加载错误后的事件
- img.onerror = function () {
- error && error.call(img);
- onready.end = true;
- img = img.onload = img.onerror = null;
- };
-
- // 图片尺寸就绪
- onready = function () {
- newWidth = img.width;
- newHeight = img.height;
- if (newWidth !== width || newHeight !== height ||
- // 如果图片已经在其他地方加载可使用面积检测
- newWidth * newHeight > 1024
- ) {
- ready.call(img);
- onready.end = true;
- }
- };
- onready();
-
- // 完全加载完毕的事件
- img.onload = function () {
- // onload在定时器时间差范围内可能比onready快
- // 这里进行检查并保证onready优先执行
- !onready.end && onready();
-
- load && load.call(img);
-
- // IE gif动画会循环执行onload,置空onload即可
- img = img.onload = img.onerror = null;
- };
-
- // 加入队列中定期执行
- if (!onready.end) {
- list.push(onready);
- // 无论何时只允许出现一个定时器,减少浏览器性能损耗
- if (intervalId === null) intervalId = setInterval(tick, 40);
- }
- };
- })();
-
- // GM_addStyle function is not existed in chrome 27
- var GM_addStyle = GM_addStyle || function(css) {
- var style = document.createElement("style");
- style.type = "text/css";
- style.appendChild(document.createTextNode(css));
- document.getElementsByTagName("head")[0].appendChild(style);
- };
-
- // 增加自定义样式
- GM_addStyle("\
- #miniblogImgPop {\
- border: 7px solid rgba(255,255,255,1);\
- box-shadow: 0 1px 30px rgba(0, 0, 0, 0.75), 0 0 40px rgba(0, 0, 0, 0.25) inset;\
- z-index: 12345;\
- opacity: 0;\
- margin-top: 0;\
- position: absolute;\
- visibility: hidden;\
- max-width: 500px;\
- transition: opacity 0.2s ease-out 0s, margin-top 0.2s ease-out 0s;\
- }\
- ");
-
- // 增加自定义样式
- GM_addStyle("\
- .miniblogImgPop-mask {\
- background: rgb(0, 0, 0);\
- z-index: 999;\
- position: absolute;\
- transition: opacity 0.4s ease-out 0;\
- }\
- ");
-
- })();