🏠 返回首頁 

Greasy Fork is available in English.

tieba.ui

贴吧对话框 for GreaseMonkey 2.x

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