tieba.ui

贴吧对话框 for GreaseMonkey 2.x

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/2657/7292/tiebaui.js

  1. /**
  2. * @package org.jixun.tieba.ui
  3. * @author jixun
  4. * @source http://tb1.bdstatic.com/tb/static-common/lib/tb_lib_04e7791.js
  5. */
  6.  
  7. // Debugging
  8. // var unsafeWindow = window;
  9.  
  10. // 配置项目参见 $.dialog.setting 的值
  11. // new $.dialog ( { 配置 } )
  12.  
  13. // 静态函数已经在相关函数注释了
  14. // $.dialog.open
  15. // $.dialog.ask
  16. // ...
  17.  
  18. (function ($) {
  19. $.fn.draggable = function(opt) {
  20. var $that = this;
  21. opt = $.extend({
  22. handle: $that,
  23. start: $.noop,
  24. stop: $.noop
  25. }, opt);
  26.  
  27. var _element = $that[0],
  28. _elementParent = $that.parent()[0];
  29.  
  30. var _getPos = function (ele) {
  31. var addOn = ele.offsetParent != _elementParent && ele.offsetParent
  32. ? _getPos (ele.offsetParent)
  33. : {x: 0, y: 0};
  34.  
  35. return {
  36. x: ele.offsetLeft + addOn.x,
  37. y: ele.offsetTop + addOn.y
  38. };
  39. };
  40.  
  41. var baseOffset, offset, isDrag;
  42. var _mouseDown = function (e) {
  43. baseOffset = _getPos (_element);
  44. offset = {
  45. x: e.pageX,
  46. y: e.pageY
  47. };
  48.  
  49. isDrag = true;
  50. e.preventDefault();
  51. opt.start();
  52. }, _mouseUp = function () {
  53. isDrag = false;
  54. opt.stop ();
  55. }, _mouseMove = function (e) {
  56. if (!isDrag) return;
  57.  
  58. $that.css ({
  59. left: baseOffset.x + e.pageX - offset.x,
  60. top : baseOffset.y + e.pageY - offset.y
  61. });
  62. };
  63.  
  64. opt.handle.on('mousedown', _mouseDown);
  65. $(document)
  66. .on ('mousemove', _mouseMove)
  67. .on ('mouseup', _mouseUp);
  68.  
  69. return function () {
  70. opt.handle.off ('mousedown', _mouseDown);
  71. $(document)
  72. .off ('mousemove', _mouseMove)
  73. .off ('mouseup', _mouseUp);
  74. };
  75. };
  76.  
  77. $.getzIndex = function () {
  78. $.zIndex = $.zIndex || 50000;
  79. return $.zIndex ++;
  80. };
  81.  
  82. var $modal = function (opts) {
  83. var that = this;
  84. this.cfg = $.extend({}, {
  85. className: "dialogJmodal",
  86. resizeable: true
  87. }, opts);
  88.  
  89. this.element =
  90. $('<div>')
  91. .addClass(this.cfg.className)
  92. .appendTo(document.body)
  93. .css({
  94. display: "none",
  95. zIndex: $.getzIndex(),
  96. width: this.width(),
  97. height: this.height()
  98. });
  99.  
  100. if (this.cfg.show)
  101. this.show ();
  102.  
  103. this.resizeFunc = function () {
  104. that.css({
  105. width: that.width (),
  106. height: that.height ()
  107. });
  108.  
  109. that.triggerHandler("resize");
  110. };
  111.  
  112. if (this.cfg.resizeable) {
  113. $(unsafeWindow).on("resize", this.resizeFunc);
  114. }
  115. };
  116.  
  117.  
  118.  
  119. $modal.prototype = {
  120. constructor: $modal,
  121.  
  122. show: function () {
  123. this.element.show.apply(this.element, arguments);
  124. },
  125.  
  126. hide: function () {
  127. this.element.hide.apply(this.element, arguments);
  128. },
  129.  
  130. width: function () {
  131. return $(unsafeWindow).width();
  132. },
  133.  
  134. height: function () {
  135. return Math.max($("body").height(), $("html").height());
  136. },
  137.  
  138. css: function () {
  139. return this.element.css.apply(this.element, arguments);
  140. },
  141.  
  142. triggerHandler: function () {
  143. this.element.triggerHandler.apply(this.element, arguments);
  144. },
  145.  
  146. bind: function () {
  147. this.element.on.apply(this.element, arguments);
  148. },
  149.  
  150. remove: function () {
  151. if (this.element) {
  152. this.element.remove();
  153. }
  154. $(unsafeWindow).off("resize", this.resizeFunc);
  155. for (var t in this) {
  156. if (this.hasOwnProperty(t)) {
  157. delete this[t];
  158. }
  159. }
  160. }
  161.  
  162. // _processTages 移除
  163. // 因为全部都是兼容 IE 用代码。
  164.  
  165. };
  166.  
  167. $.modal = $modal;
  168.  
  169. var lstEvents = ["onaccept", "oncancel", "onclose", "onresize", "onhide"];
  170. var $dialog = function (dialogOpts) {
  171. var that = this;
  172. var cbOnResize = function () {
  173. if (!that.dragged) {
  174. that.element.triggerHandler("onresize");
  175. if (that.sizeTimer)
  176. clearTimeout(that.sizeTimer);
  177. that.sizeTimer = setTimeout(that.setPosition.on(that), 5)
  178. }
  179. };
  180.  
  181. $dialog.INST.push(this);
  182. this.cfg = $.extend({}, $dialog.setting, dialogOpts);
  183. if (!this.cfg.showTitle)
  184. this.cfg.draggable = false;
  185. if (null != this.cfg.top || null != this.cfg.left) {
  186. this.cfg.autoCenter = false;
  187. }
  188.  
  189. var dialogClass = "dialogJ dialogTiebaUi";
  190.  
  191. if (this.cfg.holderClassName)
  192. dialogClass += " " + this.cfg.holderClassName;
  193.  
  194. if (this.cfg.fixed)
  195. dialogClass += " dialogJfix";
  196.  
  197. if (this.cfg.showShadow)
  198. dialogClass += " dialogJshadow";
  199.  
  200. if (this.cfg.modal) {
  201. var modalArg = {};
  202.  
  203. if (this.cfg.modalClassName)
  204. modalArg.className = this.cfg.modalClassName;
  205.  
  206. this.modal = new $.modal(modalArg);
  207. }
  208.  
  209. this.element =
  210. $('<div class="' + dialogClass + '"></div>')
  211. .hide ()
  212. .css({
  213. zIndex: $.getzIndex()
  214. }).appendTo(document.body);
  215.  
  216. this.elementWrapper = $('<div>').addClass('uiDialogWrapper').appendTo(this.element);
  217.  
  218. // 准备对话框标题
  219. this._setupTitleBar();
  220. this.setTitle(this.cfg.title);
  221. this._setupNoTitle();
  222.  
  223. // 准备对话框内容
  224. this._setupContent();
  225. if ('iframe' === this.cfg.contentType) {
  226. this.cfg.html = $("<iframe>").css({
  227. width: "100%",
  228. height: "100%",
  229. border: "none"
  230. }).attr({
  231. src: this.cfg.html
  232. });
  233. }
  234. this.setContent(this.cfg.html);
  235.  
  236. // 设定对话框宽、高
  237. // Jixun: 设定默认 400x80 的宽高。
  238. this.width(this.cfg.width);
  239. this.height(this.cfg.height);
  240. this.setPosition(this.cfg.left, this.cfg.top);
  241.  
  242. if (this.cfg.show)
  243. this.show();
  244.  
  245. if (this.cfg.autoCenter )
  246. $(unsafeWindow).on("resize", cbOnResize);
  247.  
  248. // 设定拖动
  249. this._setScroll ();
  250. $.each (lstEvents, function (i, eventName) {
  251. if (that.cfg[eventName]) {
  252. that.on(eventName, that.cfg[eventName]);
  253. }
  254. });
  255.  
  256. if (this.cfg.escable)
  257. this._setupEscKey();
  258.  
  259. // 关闭对话框
  260. this.close = function () {
  261. // 如果拒绝关闭则返回
  262. if (that.element.triggerHandler("onclose") === false)
  263. return false;
  264.  
  265. // 取消绑定 resize 事件
  266. $(unsafeWindow).off("resize", cbOnResize);
  267.  
  268. // 移除 modal
  269. if (that.modal)
  270. that.modal.remove();
  271.  
  272. that._setScroll(true);
  273. that.element.remove();
  274.  
  275. for (var t = 0; t < $dialog.INST.length; t++) {
  276. if ($dialog.INST[t] == that) {
  277. $dialog.INST.splice(t, 1);
  278. break;
  279. }
  280. }
  281.  
  282. return true;
  283. }
  284. };
  285.  
  286. $.extend($dialog, {
  287. /**
  288. * 启动一个基本对话框
  289. * @param content 对话框内容
  290. * @param opts 其它传参
  291. * @returns {$dialog}
  292. */
  293. open: function (content, opts) {
  294. return (new $dialog($.extend({}, opts, {html: content})));
  295. },
  296.  
  297. /**
  298. * 创建一个询问对话框
  299. * @param html 对话框内容
  300. * @param arrAnswers 回答按钮内容
  301. *
  302. * @param callback 两个参数, 原型如下:
  303. * callback (i, $dialog)
  304. * i 为回答按钮序号, $dialog 为对话框本体
  305. * this 绑定为 $(按钮)。
  306. *
  307. * @param opts 创建时传递给 $dialog / $modal 的参数
  308. * @returns {}
  309. */
  310. ask: function (html, arrAnswers, callback, opts) {
  311. if (!opts) opts = {};
  312.  
  313. var _$dialog = new $dialog($.extend({modal: true}, opts, {html: html || "", show: true}));
  314.  
  315. if ($.isArray(arrAnswers) && arrAnswers.length) {
  316. var answerContainer = $('<div>')
  317. .addClass('dialogJanswers')
  318. .appendTo(_$dialog.elementWrapper);
  319.  
  320. $(arrAnswers).each (function (i, val) {
  321. //answerContainer.append ($('<input>').val(val).addClass('dialogJbtn').attr('type', 'button'))
  322. // .append (' ');
  323.  
  324. // 下面这个的按钮有蓝色样式
  325. answerContainer
  326. .append (
  327. $('<a>').addClass('ui_btn ui_btn_m').append($('<span>').append('<em>').text(val))
  328. .click (function () {
  329. if (false !== callback.call(this, i, _$dialog))
  330. _$dialog.close();
  331. })
  332. );
  333. });
  334.  
  335. _$dialog.buttons = $("input", answerContainer);
  336. }
  337. _$dialog.setPosition();
  338.  
  339. if (opts.show)
  340. _$dialog.show();
  341. return _$dialog;
  342. },
  343.  
  344. /**
  345. * 显示一条警告框
  346. * @param message 警告消息
  347. * @param [opts] $modal / $dialog 参数
  348. * @param opts.acceptValue 「确定」按钮标题
  349. * @returns {$dialog}
  350. */
  351. alert: function (message, opts) {
  352. var extOpts = $.extend({}, opts || {});
  353. return $dialog.ask(message, [extOpts.acceptValue || "确定"], function (e, t) {
  354. return t.element.triggerHandler(lstEvents[e], this)
  355. }, extOpts)
  356. },
  357.  
  358. /**
  359. * 显示一个确认框
  360. * @param message 确认的消息
  361. * @param [opts] $modal / $dialog 参数
  362. * @param opts.acceptValue 「确定」按钮标题
  363. * @returns {$dialog}
  364. */
  365. confirm: function (message, opts) {
  366. var extOpts = $.extend({}, opts || {});
  367. return $dialog.ask(message, [extOpts.acceptValue || "确定", extOpts.cancelValue || "取消"], function (e, t) {
  368. return t.element.triggerHandler(lstEvents[e], this)
  369. }, extOpts)
  370. },
  371.  
  372. /**
  373. * 显示一个定时警告框
  374. * @param message 显示的消息
  375. * @param callback 回调, 无参数
  376. * @param [opts] 参数集合
  377. * @param opts.acceptValue 「确定」按钮标题
  378. * @param {Boolean} opts.button 是否显示确定按钮
  379. * @param opts.time 等待时长
  380. * @returns {*}
  381. */
  382. assert: function (message, callback, opts) {
  383. var extOpts = $.extend({button: true}, opts || {});
  384.  
  385. if (2 == arguments.length) {
  386. extOpts = callback;
  387. callback = $.noop;
  388. }
  389.  
  390. var $dialogAsk = $dialog.ask(
  391. message,
  392. extOpts.button ? [extOpts.acceptValue || "确定"] : [],
  393. function (i, $dialog) {
  394. return $dialog.element.triggerHandler(lstEvents[i], this)
  395. },
  396. extOpts
  397. );
  398.  
  399. setTimeout(function () {
  400. if ($dialogAsk && $dialogAsk.close)
  401. $dialogAsk.close();
  402.  
  403. if (callback)
  404. callback();
  405.  
  406. }, parseInt(extOpts.time) || 2000);
  407.  
  408. return $dialogAsk;
  409. },
  410.  
  411. /**
  412. * 远端加载一个页面并显示其内容
  413. * @param url 目标地址
  414. * @param opts 选项
  415. * @param opts.filter 页面内容选择器
  416. * @param opts.cache 参见 jQuery.ajax
  417. * @param opts.type 参见 jQuery.ajax
  418. * @returns {$dialog}
  419. */
  420. load: function (url, opts) {
  421. opts = opts || {};
  422. var _$dialog = new $dialog(opts);
  423. var requestObj = {
  424. url: url,
  425. type: "GET",
  426. dataType: "html",
  427. cache: false,
  428. success: function (html) {
  429. if (opts.filter)
  430. html = $(opts.filter, html);
  431.  
  432. _$dialog.setContent(html);
  433. }
  434. };
  435.  
  436. $.each(["type", "cache"], function (i, str) {
  437. if (opts.hasOwnProperty(str)) {
  438. requestObj[str] = opts[str];
  439. delete opts[str];
  440. }
  441. });
  442.  
  443. $.ajax(requestObj);
  444. return _$dialog;
  445. },
  446.  
  447. /**
  448. * 关闭所有开启的对话框
  449. */
  450. close: function () {
  451. for (var i = 0; i < this.INST.length; i++) {
  452. // 如果拒绝关闭, i-- 然后继续枚举关闭过程
  453. if (false !== this.INST[i].close()) {
  454. i--;
  455. }
  456. }
  457. },
  458.  
  459. setting: {
  460. modal: true,
  461. showShadow: true,
  462. showTitle: true,
  463. noTitle: false,
  464.  
  465. // 默认 400 x 80
  466. width: 400,
  467. height: 80,
  468. fixed: true,
  469. left: null,
  470. top: null,
  471. show: true,
  472. closeable: true,
  473. hideOnclose: false,
  474. draggable: true,
  475. contentType: null,
  476. resizeable: false,
  477. closeTips: null,
  478. escable: true,
  479. scrollable: true,
  480. modalClassName: null,
  481. autoCenter: true,
  482. html: null,
  483. minWidth: 200,
  484. minHeight: 100,
  485. maxWidth: null,
  486. maxHeight: null
  487. }
  488. });
  489.  
  490. $dialog.prototype = {
  491. constructor: $dialog,
  492.  
  493. /**
  494. * 擦除原始标题并设定新标题
  495. * 可以为 jQuery 对象、DOM 对象
  496. * @param newTitle
  497. */
  498. setTitle: function (newTitle) {
  499. this.element.find(".dialogJtitle>span.dialogJtxt").html(newTitle || "");
  500. },
  501.  
  502. /**
  503. * 擦除原始内容并设定新内容
  504. * 可以为 jQuery 对象、DOM 对象
  505. * @param newContent
  506. */
  507. setContent: function (newContent) {
  508. newContent && this.element.find(".dialogJbody").html(newContent);
  509. },
  510.  
  511. /**
  512. * 设定新宽度
  513. * @param newWidth
  514. * @returns {*}
  515. */
  516. width: function (newWidth) {
  517. return this.element.css("width", newWidth);
  518. },
  519.  
  520. /**
  521. * 设定新高度
  522. * @param newHeight
  523. * @returns {*}
  524. */
  525. height: function (newHeight) {
  526. return $(".dialogJbody", this.element).css("height", newHeight);
  527. },
  528.  
  529. /**
  530. * 设定对话框位置
  531. * @param [left] 左边, 留空居中
  532. * @param [top] 右边, 留空居中
  533. */
  534. setPosition: function (left, top) {
  535. if (!$.isNumeric(left) && !$.isNumeric(top)) {
  536. var $doc = $(document),
  537. $win = $(unsafeWindow),
  538. newPosOffset = this.cfg.fixed ? [0, 0] : [$doc.scrollLeft(), $doc.scrollTop()];
  539.  
  540. left = newPosOffset [0] + ($win.width() - this.element.outerWidth() ) / 2;
  541. top = newPosOffset [1] + ($win.height() - this.element.outerHeight()) / 2;
  542.  
  543. if (top < 0) top = 0;
  544. }
  545.  
  546. this.element.css({
  547. left: left,
  548. top: top
  549. });
  550.  
  551. this.triggerHandler("resize");
  552. },
  553. /**
  554. * 获取标题 (HTML)
  555. * @returns {String}
  556. */
  557. getTitle: function () {
  558. return this.element.find(".dialogJtitle>span").html();
  559. },
  560. /**
  561. * 获取标题文本
  562. * @returns {String}
  563. */
  564. getTitleText: function () {
  565. return this.element.find(".dialogJtitle").text();
  566. },
  567.  
  568. /**
  569. * 获取对话框内容 (HTML)
  570. * @returns {String}
  571. */
  572. getContent: function () {
  573. return $(".dialogJbody", this.element).html()
  574. },
  575. /**
  576. * 获取对话框内容
  577. * @returns {String}
  578. */
  579. getContentText: function () {
  580. return $(".dialogJbody", this.element).text()
  581. },
  582.  
  583. /**
  584. * 显示对话框
  585. */
  586. show: function () {
  587. this.element.show.apply(this.element, arguments);
  588.  
  589. if (this.modal) {
  590. this.modal.cfg.safety = this.element;
  591. this.modal.show.apply(this.modal, arguments);
  592. }
  593. },
  594.  
  595. /**
  596. * 隐藏对话框
  597. * @returns {boolean}
  598. */
  599. hide: function () {
  600. if (this.element.triggerHandler("onhide") === false)
  601. return false;
  602.  
  603. this.element.hide.apply(this.element, arguments);
  604. if (this.modal)
  605. this.modal.hide.apply(this.modal, arguments);
  606.  
  607. return true;
  608. },
  609.  
  610. /**
  611. * 获取对话框 DOM 元素
  612. * @returns {HTMLElement}
  613. */
  614. getElement: function () {
  615. return this.element[0];
  616. },
  617.  
  618. /**
  619. * 绑定事件
  620. * @returns {$dialog}
  621. */
  622. bind: function () {
  623. this.element.on.apply(this.element, arguments);
  624. return this;
  625. },
  626.  
  627. /**
  628. * 触发事件
  629. */
  630. triggerHandler: function () {
  631. this.element.triggerHandler.apply(this.element, arguments);
  632. },
  633.  
  634. /**
  635. * 获取按钮
  636. * @returns {Array|undefined}
  637. */
  638. getButtons: function () {
  639. return this.buttons;
  640. },
  641.  
  642. /**
  643. * 内部函数: 设定无标题对话框
  644. * @private
  645. */
  646. _setupNoTitle: function () {
  647. if (this.cfg.noTitle) {
  648. $(".dialogJtitle").css({
  649. "border-bottom": 0,
  650. "background-color": "#fff"
  651. });
  652. }
  653. },
  654.  
  655. /**
  656. * 内部函数: 设定对话框标题栏
  657. * @private
  658. */
  659. _setupTitleBar: function () {
  660. if (this.cfg.showTitle) {
  661. var that = this;
  662. var titleBar = that.titleBar =
  663. $('<div>').append(
  664. $('<span>').addClass('dialogJtxt')
  665. ).addClass('dialogJtitle')
  666. .appendTo(this.elementWrapper);
  667.  
  668. if (this.cfg.closeable) {
  669. $('<a>').addClass('dialogJclose').attr({
  670. title: this.cfg.closeTips || "关闭本窗口",
  671. href: '#'
  672. }).text(' ').appendTo(titleBar)
  673. .on ('mousedown', function (e) {
  674. e.stopPropagation();
  675. }).click(function () {
  676. if (that.cfg.hideOnclose) {
  677. that.hide()
  678. } else {
  679. that.close();
  680. }
  681. return false;
  682. });
  683.  
  684. if (this.cfg.draggable) {
  685. titleBar.css ({
  686. cursor: 'move'
  687. });
  688.  
  689. var _rmDrag = $(that.element).draggable({
  690. handle: titleBar,
  691. start: function () {
  692. that._setupHackDiv(1)
  693. },
  694. stop: function () {
  695. that.dragged = true;
  696. that._setupHackDiv(0);
  697. }
  698. });
  699. $(that.element).on("onclose", _rmDrag);
  700. }
  701. }
  702. }
  703. },
  704.  
  705. _setupHackDiv: function (bShowHackDiv) {
  706. var _$dialog = this;
  707. if (bShowHackDiv) {
  708. if ($("IFRAME", _$dialog.element).length) {
  709. var $content = $(".dialogJcontent", _$dialog.element);
  710. if (!_$dialog.hack_div) {
  711. _$dialog.hack_div = $("<div>").appendTo($content).css({
  712. position: "absolute",
  713. left: 0,
  714. top: 0,
  715. cursor: "move"
  716. });
  717. }
  718. _$dialog.hack_div.show().css({
  719. width: _$dialog.element.outerWidth(),
  720. height: _$dialog.element.outerHeight()
  721. })
  722. }
  723. } else {
  724. if (_$dialog.hack_div)
  725. _$dialog.hack_div.hide ();
  726. }
  727. },
  728.  
  729. _setupEscKey: function () {
  730. var $that = this;
  731.  
  732. var _escKeyCb = function (n) {
  733. // ESC - 0x1b
  734. if (0x1b == n.which) {
  735. if ($that.showTitle) {
  736. $(".dialogJclose", $that.titleBar).triggerHandler("click")
  737. } else {
  738. $that.close();
  739. }
  740. }
  741. };
  742.  
  743. $(document).on("keydown", _escKeyCb);
  744. $($that.element).on("onclose", function () {
  745. $(document).off("keydown", _escKeyCb)
  746. });
  747. },
  748.  
  749. _setupContent: function () {
  750. this.elementWrapper.append(
  751. $('<div>').addClass('dialogJcontent').append(
  752. $('<div>').addClass('dialogJbody')));
  753. },
  754.  
  755. _setScroll: function (bSetScroll) {
  756. if (this.cfg.modal && !this.cfg.scrollable) {
  757. var htmlRoot = $("html");
  758. if (htmlRoot.length) {
  759. var i = htmlRoot[0].scrollTop;
  760. if (bSetScroll) {
  761. htmlRoot.css({
  762. overflow: this.element.data("htmlOverflow") || "",
  763. paddingRight: 0
  764. });
  765. } else {
  766. if (htmlRoot[0].style.overFlow) {
  767. this.element.data("htmlOverflow", htmlRoot[0].style.overFlow);
  768. }
  769.  
  770. htmlRoot.css({
  771. overflow: "hidden",
  772. paddingRight: 17
  773. })
  774. }
  775.  
  776. htmlRoot[0].scrollTop = i
  777. }
  778. }
  779. }
  780. };
  781.  
  782. $.each(lstEvents, function (e, t) {
  783. $dialog.prototype[t] = function (e) {
  784. this.on(t, e)
  785. }
  786. });
  787. $dialog.INST = [];
  788. $.dialog = $dialog;
  789. })(jQuery);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址