找到493个回复 (用户: 无名啊)
@老虎会游泳,感觉可以和
viewer
作者协调下,去掉$(document).ready()
你也说多个
$(document).ready()
执行顺序不定,不利于后面脚本按顺序执行
@老虎会游泳,不对噢,
viewer
加了defer
,那就是你先执行
$(document).ready()
,然后解析完DOM后,viewer
再执行$(document).ready()
。触发
DOMContentLoaded
后,你先绑定onclick
,再由viewer
绑定?所以,你的也应该加上
defer
?
@老虎会游泳,你的插件排在
viewer
之后,并且也用$(document).ready()
的话,是不是就能在viewer
绑定onclick
后执行了?
@老虎会游泳,不是,之前你的版本,最后存活的
onclick
是viewer
的,导致没法点击后加载
@老虎会游泳,我理解错了?https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script#attr-defer
defer
布尔属性被设定用来通知浏览器该脚本将在文档完成解析后,触发DOMContentLoaded (en-US)
事件前执行。
有defer
属性的脚本会阻止DOMContentLoaded
事件,直到脚本被加载并且解析完成。
@老虎会游泳,我好奇为何你的脚本会和图片浏览器(下称
viewer
)冲突按说,
viewer
是defer
,在DOMContentLoaded
之前执行,(之前)你的在触发后执行,应该是可以由你保存好viewer
的onclick
,最后存活的onclick
是你的啊
@老虎会游泳,我感觉
DOMContentLoaded
触发后,各个图片都下了一小点了(所以也经常会闪烁一下才消失),也不知道能不能利用上那些拦截广告的,也不知道怎么做到不会有闪烁就过滤掉广告的,感觉像浏览器解析DOM前,就过滤掉了
@老虎会游泳,旧图片、外站图片、音乐、视频啥的,好像没有提供文件大小
对这些情况,有啥更好的办法吗(除了
HEAD
再查询一次)
@老虎会游泳,我用的我7楼的代码,有小概率能用上图片浏览器(此时正常,点击按钮重现图片后也正常),大部分时候被你的 footer.js 代替了,点击图片就新窗口打开
@老虎会游泳,我改写了下,主要更新内容:
- 按钮变得好看些
- 自动使图片、音乐、视频、内嵌HTML变成点击显示
- 自动检测目标链接文件大小。对于图片,若已缓存或较小(如 < 1MB),则直接显示
感觉还存在以下问题:
不知道有没有直接获取文件大小的方法。
目前是用
fetch
以HEAD
方法再发送一次请求,解析content-length
判定文件大小。
- 会不会有啥安全问题?
- 会不会跨域啥的获取不了大小?
- 会不会哪个服务器把
HEAD
当GET
看,直接返回整个文件?还是和图片浏览器插件冲突。
按理说,我保留了原始
img
节点,onclick
啥的应该都还保留着?@老虎会游泳,有空能指教下,问题出哪儿不?
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <script> const blocks = { userimg: {type: 'img', icon: 'image'}, iframe_box: {type: 'iframe', icon: 'web'}, audio_box: {type: 'audio', icon: 'audiotrack'}, video_box: {type: 'video', icon: 'movie'}, }; function formatSize(size) { const i = size && Math.floor(Math.log(size) / Math.log(1024)); return (size / (1 << (10 * i))).toFixed(i && 2) + ' ' + ' KMGT'[i].trim() + 'B'; } customElements.define('my-button', class extends HTMLElement { #ref = {}; #orig_node; #media_src; #media_node; #createElementFromObject(obj) { let el = document.createElement(obj.tag); for (const k in obj) { if (k === 'children') obj.children.forEach(c => el.appendChild(this.#createElementFromObject(c))); else if (k === 'text') el.textContent = obj[k]; else if (k === 'ref') this.#ref[obj[k]] = el; else if (k !== 'tag') el.setAttribute(k, obj[k]); } return el; } constructor() { super(); // 创建一个 shadow root let shadow = this.attachShadow({mode: 'open'}); [ {tag: 'link', rel: 'stylesheet', href: 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css'}, {tag: 'link', rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons'}, {tag: 'script', src: 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js'}, {tag: 'button', class: 'mdc-fab mdc-fab--extended', style: 'margin: 10px', children: [ {tag: 'div', class: 'mdc-fab__ripple'}, {tag: 'span', class: 'material-icons mdc-fab__icon', ref: 'icon'}, {tag: 'span', class: 'mdc-fab__label', ref: 'text'}, ]}, {tag: 'style', text: ` :host { /* --mdc-theme-primary: #e74c3c; */ --mdc-theme-secondary: #fafafa; /* --mdc-theme-background: #f00; */ /* --mdc-theme-on-primary: #fff; */ --mdc-theme-on-secondary: #2c3e50; } `}, ].forEach(x => shadow.appendChild(this.#createElementFromObject(x))); this.onclick = this.recover; } get text() { return this.#ref.text.textContent; } set text(s) { this.#ref.text.textContent = s; } get icon() { return this.#ref.icon.textContent; } set icon(s) { this.#ref.icon.textContent = s; } // onclick() { // 为什么不能这样重写方法?? recover() { this.#media_node.src &&= this.#media_src; this.parentNode.replaceChild(this.#orig_node, this); delete this; } // 替换掉旧节点,展示本按钮 replace(root_node, media_node) { this.#orig_node = root_node.parentNode.replaceChild(this, root_node); this.#media_node = media_node; this.#media_src = media_node.src; media_node.src &&= ' '; // 询问目标链接大小,太大则等待用户选择,较小直接显示 if (this.#media_src) { fetch(this.#media_src, {method: 'HEAD'}).then(resp => { if (resp.ok) { const size = parseInt(resp.headers.get('content-length')); if (size < (1 << 20) && this.icon === blocks.userimg.icon) this.recover(); else if (size > 0) this.text += `(${formatSize(size)})`; } }); } } }); document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll(Object.keys(blocks).map(x => `.${x}`).join()).forEach(x => { // 获取 element 类型、显示按钮时的图标 const {type, icon} = Object.entries(blocks).find(([k]) => x.classList.contains(k))[1]; // 若图片已下载完毕,就让它显示吧 if (type === 'img' && x.complete) return; // 获取真正的多媒体节点 const media_node = ['audio', 'video'].includes(type) ? x.querySelector(type) : x; // 图片有外层链接,则准备替换整个外层 if (type === 'img' && x.parentNode.href) x = x.parentNode; // 创建按钮 let el = document.createElement('my-button'); el.icon = icon; el.text = type === 'iframe' ? '内嵌网页' : media_node.alt || media_node.src; el.replace(x, media_node); }); }); </script>