Space-efficient Youtube

AKA: "Wide Youtube", AKA: "Wide video container" - Uses the page space on youtube more efficiently (especially good for high resolutions)

当前为 2021-03-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Space-efficient Youtube
  3. // @namespace 1N07
  4. // @author 1N07
  5. // @icon https://i.imgur.com/VgEiyi3.png
  6. // @icon64 https://i.imgur.com/VgEiyi3.png
  7. // @description AKA: "Wide Youtube", AKA: "Wide video container" - Uses the page space on youtube more efficiently (especially good for high resolutions)
  8. // @include https://www.youtube.com/*
  9. // @version 2.3.3
  10. // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_unregisterMenuCommand
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @noframes
  16. // ==/UserScript==
  17.  
  18. (function() {
  19. if(true)
  20. {
  21. var configCSS = `
  22. #SEYConfig {
  23. width: 320px !important;
  24. height: 670px !important;
  25. max-height: 100% !important;
  26. border: none !important;
  27. border-radius: 0 0 0 20px !important;
  28. box-shadow: black -1px 1px 20px;
  29. position: fixed !important;
  30. top: 0 !important;
  31. right: 0 !important;
  32. left: unset !important;
  33. background: #383838 !important;
  34. }
  35.  
  36. #SEYConfig_wrapper
  37. {
  38. padding: 10px;
  39. background-color: #212121;
  40. color: white;
  41. background-color: transparent;
  42. }
  43.  
  44. #SEYConfig .config_var
  45. {
  46. padding: 1px 20px;
  47. }
  48.  
  49. #SEYConfig input
  50. {
  51. background-color: #181818;
  52. color: white;
  53. border: none;
  54. float: left;
  55. margin-right: 5px;
  56. }
  57.  
  58. #SEYConfig input[type="text"]
  59. {
  60. width: 40px;
  61. text-align: center;
  62. }
  63.  
  64. #SEYConfig input[type="checkbox"]
  65. {
  66. filter: invert(90%);
  67. }
  68.  
  69. #SEYConfig .saveclose_buttons
  70. {
  71. background-color: #181818;
  72. color: white;
  73. border-color: gray;
  74. }
  75.  
  76. #SEYConfig .section_header {
  77. background: #202020;
  78. margin-bottom: 5px;
  79. }
  80.  
  81. #SEYConfig .section_header_holder {
  82. margin-top: 8px;
  83. background-color: rgba(0,0,0,0.3);
  84. padding: 0 0 5px 0;
  85. border-radius: 0 0 10px 10px;
  86. }
  87.  
  88. #SEYConfig_resetLink { color: white !important; }
  89. `;
  90. }
  91.  
  92. var frame = document.createElement('div');
  93. frame.id = "SEYConf";
  94. document.body.appendChild(frame);
  95.  
  96. GM_config.init(
  97. {
  98. 'id': 'SEYConfig', // The id used for this instance of GM_config
  99. 'title': 'Space-efficient Youtube Config',
  100. 'fields': // Fields object
  101. {
  102. 'FPPCompOn': // This is the id of the field
  103. {
  104. 'section': 'Fade++',
  105. 'label': 'Fade++ compatibility mode', // Appears next to field
  106. 'type': 'checkbox', // Makes this setting a text field
  107. 'default': false // Default value if user doesn't change it
  108. },
  109.  
  110. 'HomeVideoContainerWidth':
  111. {
  112. 'section': 'Home page',
  113. 'label': 'Video container width',
  114. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  115. 'type': 'unsigned float',
  116. 'default': '360'
  117. },
  118. 'HideChannelIconNextToVideosOnHomePage':
  119. {
  120. 'label': 'Hide channel icon in video container',
  121. 'type': 'checkbox',
  122. 'default': false
  123. },
  124.  
  125. 'SubVideoContainerWidth':
  126. {
  127. 'section': 'Subscriptions page',
  128. 'label': 'Video container width',
  129. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  130. 'type': 'unsigned float',
  131. 'default': '210'
  132. },
  133.  
  134. 'TrendingVideoContainerWidth':
  135. {
  136. 'section': 'Trending page',
  137. 'label': 'Video container width',
  138. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  139. 'type': 'unsigned float',
  140. 'default': '600'
  141. },
  142. 'TrendingVideoContainerHeight':
  143. {
  144. 'label': 'Video container height',
  145. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  146. 'type': 'unsigned float',
  147. 'default': '138'
  148. },
  149.  
  150. 'HQTN':
  151. {
  152. 'section': 'Subscriptions & Trending pages',
  153. 'label': 'Load high quality thumbnails',
  154. 'title': 'The default thumbnail resolution is fitted for the default video container size, so if you use defaults(or smaller) there is no need to enable this.',
  155. 'type': 'checkbox',
  156. 'default': false
  157. },
  158.  
  159. 'SearchVideoContainerWidth':
  160. {
  161. 'section': 'Search results page',
  162. 'label': 'Video container width',
  163. 'title': 'The width of the container which includes both the thumbnail and the title/other info',
  164. 'type': 'unsigned float',
  165. 'default': '600'
  166. },
  167. 'SearchVideoContainerHeight':
  168. {
  169. 'label': 'Video container height',
  170. 'title': 'The height of the container. This directly affects thumnail size and how much space is left for the other info',
  171. 'type': 'unsigned float',
  172. 'default': '150'
  173. },
  174. 'HideSearchVideoBadges':
  175. {
  176. 'label': 'Hide video badges',
  177. 'title': 'Hides the little badges like New/4K/CC etc. on the video containers leaving more space for the description',
  178. 'type': 'checkbox',
  179. 'default': false
  180. },
  181.  
  182. 'AutoExpandChannelVidContainers':
  183. {
  184. 'section': 'Channel pages',
  185. 'label': 'Auto-expand horizontal video lists',
  186. 'type': 'checkbox',
  187. 'default': false
  188. }
  189. },
  190. 'frame': frame,
  191. 'css': configCSS
  192. }
  193. );
  194.  
  195. var refreshAfterSave = false;
  196. GM_config.onOpen = function(doc, win, frame) {
  197. let saveBtn = $(frame).find("#SEYConfig_saveBtn");
  198. saveBtn.before(saveBtn.clone().prop("id", "SEYConfig_saveRefreshBtn").text("Save & Refresh"));
  199. $("#SEYConfig_saveRefreshBtn").click(() => {
  200. refreshAfterSave = true;
  201. $("#SEYConfig_saveBtn").click();
  202. });
  203. };
  204. GM_config.onSave = function(){
  205. $("#SEYConfig .reset_holder").prepend(`<span id="SEYCSavedNotif" style="float: left; margin: 0 0 5px 5px; color: green; font-size: 18px; font-weight: bold;">Saved!</span>`).hide().fadeIn(200, () => {
  206. if(refreshAfterSave)
  207. location.reload();
  208. setTimeout(() => {
  209. $("#SEYCSavedNotif").fadeOut(200, () => {
  210. $("#SEYCSavedNotif").remove();
  211. });
  212. }, 1800);
  213. });
  214. };
  215.  
  216. var FPPCompOn = GM_config.get('FPPCompOn');
  217. var HomeVideoContainerWidth = CleanNumber(GM_config.get('HomeVideoContainerWidth'));
  218. var HideChannelIconNextToVideosOnHomePage = GM_config.get('HideChannelIconNextToVideosOnHomePage');
  219. var SubVideoContainerWidth = CleanNumber(GM_config.get("SubVideoContainerWidth"));
  220. var TrendingVideoContainerWidth = CleanNumber(GM_config.get('TrendingVideoContainerWidth'));
  221. var TrendingVideoContainerHeight = CleanNumber(GM_config.get('TrendingVideoContainerHeight'));
  222. var HQTN = GM_config.get('HQTN');
  223. var SearchVideoContainerWidth = CleanNumber(GM_config.get('SearchVideoContainerWidth'));
  224. var SearchVideoContainerHeight = CleanNumber(GM_config.get('SearchVideoContainerHeight'));
  225. var HideSearchVideoBadges = GM_config.get('HideSearchVideoBadges');
  226. var AutoExpandChannelVidContainers = GM_config.get('AutoExpandChannelVidContainers');
  227.  
  228.  
  229. GM_registerMenuCommand("Settings", () => {
  230. if(!GM_config.isOpen)
  231. GM_config.open();
  232. });
  233.  
  234. const ratioMultiplier = 16 / 9;
  235. var screenWidth = screen.width;
  236. if(!!document.getElementById("early-body")) { //if old youtube
  237. document.getElementById("content").setAttribute("style", "width: 99%;");
  238. } else { //new youtube
  239. //Main container width and padding
  240. if(true) {
  241. addGlobalStyle(`
  242. /*search*/
  243. ytd-search ytd-two-column-search-results-renderer.ytd-search,
  244. ytd-search ytd-two-column-search-results-renderer.ytd-search > #primary,
  245. /*home*/
  246. ytd-browse[page-subtype="home"] #contents.ytd-rich-grid-renderer,
  247. /*other*/
  248. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse
  249. {
  250. width: 100% !important;
  251. max-width: 100% !important;
  252. }
  253.  
  254. ytd-browse > ytd-two-column-browse-results-renderer.ytd-browse > #primary,
  255. ytd-search
  256. {
  257. padding: 16px;
  258. }
  259. `);
  260. }
  261.  
  262. //vertical lists to horizontal grid / video container sizing
  263. if(true) {
  264. //trending
  265. if(true) {
  266. addGlobalStyle(`
  267. /*container*/
  268. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  269. {
  270. display: inline-block;
  271. width: `+TrendingVideoContainerWidth+`px;
  272. height: `+TrendingVideoContainerHeight+`px;
  273. }
  274. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer > #dismissable
  275. {
  276. width: 100%;
  277. height: 100%;
  278. }
  279.  
  280. /*thumnail container*/
  281. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail.ytd-video-renderer,
  282. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail
  283. {
  284. height: 100%;
  285. width: `+(TrendingVideoContainerHeight * ratioMultiplier)+`px;
  286. }
  287.  
  288. /*thumnail shadow and image*/
  289. #grid-container.ytd-expanded-shelf-contents-renderer > ytd-video-renderer:not([use-prominent-thumbs]) ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  290. {
  291. height: 100% !important;
  292. width: 100% !important;
  293. }
  294. `);
  295. }
  296.  
  297. //search
  298. if(true) {
  299. addGlobalStyle(`
  300. /*container*/
  301. ytd-search ytd-video-renderer, ytd-search ytd-channel-renderer, ytd-search ytd-radio-renderer, ytd-search ytd-playlist-renderer
  302. {
  303. display: inline-block;
  304. width: `+SearchVideoContainerWidth+`px;
  305. height: `+SearchVideoContainerHeight+`px;
  306. box-sizing: border-box;
  307. }
  308. ytd-search ytd-video-renderer > #dismissable
  309. {
  310. width: 100%;
  311. height: 100%;
  312. }
  313.  
  314. /*thumnail container*/
  315. ytd-search ytd-video-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-video-renderer,
  316. ytd-search ytd-radio-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-radio-renderer,
  317. ytd-search ytd-playlist-renderer[use-prominent-thumbs] ytd-playlist-thumbnail.ytd-playlist-renderer
  318. {
  319. max-width: none;
  320. min-width: none;
  321. height: 100%;
  322. width: `+(SearchVideoContainerHeight * ratioMultiplier)+`px;
  323. -ms-flex: none;
  324. -webkit-flex: none;
  325. flex: none;
  326. }
  327. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  328. ytd-search ytd-playlist-renderer.ytd-item-section-renderer
  329. {
  330. display: flex;
  331. }
  332.  
  333. /*thumnail shadow and image*/
  334. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  335. ytd-search ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  336. {
  337. width: 100%;
  338. height: 100%;
  339. }
  340.  
  341. /*other*/
  342. ytd-search #description-text.ytd-video-renderer
  343. {
  344. margin-bottom: 2px;
  345. }
  346. ytd-search ytd-video-renderer > #dismissable #channel-info
  347. {
  348. padding: 2px 0 0 0;
  349. }
  350. ytd-search #description-text.ytd-video-renderer
  351. {
  352. max-height: none;
  353. }
  354. `+(HideSearchVideoBadges ? `ytd-search ytd-badge-supported-renderer { display: none; }` : ``)+`
  355.  
  356. /*channel thumnail container*/
  357. ytd-search #avatar.ytd-channel-renderer,
  358. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer .channel-link.ytd-channel-renderer,
  359. ytd-search ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer
  360. {
  361. width: min-content;
  362. width: -moz-min-content;
  363. flex: none;
  364. max-width: none;
  365. min-width: 0;
  366. }
  367.  
  368. ytd-search div.ytd-video-renderer[id="channel-info"] { padding: 3px 0 0 0 !important; }
  369. `);
  370. }
  371.  
  372. //home
  373. if(true) {
  374. addGlobalStyle(`
  375. /*container*/
  376. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  377. {
  378. width: `+HomeVideoContainerWidth+`px;
  379. }
  380. `+(HideChannelIconNextToVideosOnHomePage ? `ytd-browse[page-subtype="home"] #avatar-link.ytd-rich-grid-media { display: none; }` : ``)+`
  381. `);
  382. }
  383.  
  384. //subs
  385. if(true) {
  386. addGlobalStyle(`
  387. /*container*/
  388. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  389. {
  390. width: `+SubVideoContainerWidth+`px;
  391. }
  392.  
  393. /*thumnail container*/
  394. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail.ytd-grid-video-renderer
  395. {
  396. width: `+SubVideoContainerWidth+`px;
  397. height: `+(SubVideoContainerWidth / ratioMultiplier)+`px;
  398. }
  399.  
  400. /*thumnail shadow and image*/
  401. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail,
  402. ytd-browse[page-subtype="subscriptions"] ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail > img
  403. {
  404. width: 100%;
  405. height: 100%;
  406. }
  407. `);
  408. }
  409.  
  410. //multiple
  411. if(true) {
  412. addGlobalStyle(`#dismissible.ytd-video-renderer { height: 100%; }`);
  413. }
  414. }
  415.  
  416. //video container padding/margin
  417. if(true) {
  418. //trending
  419. if(true) {
  420. addGlobalStyle(`
  421. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer
  422. {
  423. padding: 0 10px 0 0;
  424. }
  425. #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer:not(:last-child)
  426. {
  427. margin: 0 0 10px 0;
  428. }
  429. `);
  430. }
  431.  
  432. //search
  433. if(true) {
  434. addGlobalStyle(`
  435. ytd-search ytd-video-renderer.ytd-item-section-renderer,
  436. ytd-search ytd-channel-renderer.ytd-item-section-renderer,
  437. ytd-search ytd-radio-renderer.ytd-item-section-renderer,
  438. ytd-search ytd-playlist-renderer.ytd-item-section-renderer,
  439. ytd-search #items.ytd-vertical-list-renderer > .ytd-vertical-list-renderer
  440. {
  441. padding: 0 10px 0 0;
  442. margin: 10px 0 0 0;
  443. }
  444. ytd-search ytd-shelf-renderer.ytd-item-section-renderer
  445. {
  446. margin: 10px 0 0 0;
  447. }
  448. `);
  449. }
  450.  
  451. //home
  452. if(true) {
  453. addGlobalStyle(`
  454. ytd-browse[page-subtype="home"] ytd-rich-item-renderer
  455. {
  456. margin: 0 5px 20px 5px;
  457. }
  458. ytd-browse[page-subtype="home"] ytd-rich-section-renderer
  459. {
  460. margin: 0;
  461. }
  462. `);
  463. }
  464.  
  465. //subs
  466. if(true) {
  467. addGlobalStyle(`
  468. ytd-browse[page-subtype="subscriptions"] #items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer
  469. {
  470. margin: 0 5px 15px 0;
  471. }
  472. `);
  473. }
  474. }
  475.  
  476. //channel page horizontal list arrow visibility
  477. if(true) {
  478. addGlobalStyle(`
  479. yt-horizontal-list-renderer[at-start] #left-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer,
  480. yt-horizontal-list-renderer[at-end] #right-arrow.yt-horizontal-list-renderer .arrow.yt-horizontal-list-renderer
  481. {
  482. display: block;
  483. opacity: 1;
  484. }
  485. `+(!!window.chrome ? `
  486. #left-arrow.yt-horizontal-list-renderer { left: 20px; }
  487. #right-arrow.yt-horizontal-list-renderer { right: 20px; }
  488. ` : `
  489. #left-arrow.yt-horizontal-list-renderer { left: 0px; }
  490. #right-arrow.yt-horizontal-list-renderer { right: 40px; }
  491. `)
  492. );
  493. }
  494.  
  495. if(HQTN) {
  496. addGlobalStyle(`
  497. img.yt-img-shadow:not([src*='?'])
  498. {
  499. object-fit: cover;
  500. }
  501. `);
  502. }
  503. if(FPPCompOn) {
  504. addGlobalStyle(`
  505. /*========== Fade++ Compatibility ==========*/
  506. ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]) {
  507. display: block;
  508. }
  509. ytd-app[guide-persistent-and-visible] #page-manager > ytd-browse:not([page-subtype="playlist"]) ytd-two-column-browse-results-renderer.ytd-browse
  510. {
  511. margin-left: 250px !important;
  512. }
  513. `);
  514. //console.log("Youtube Wide video container Fade++ compatibilty style added to DOM");
  515. }
  516. }
  517.  
  518. if(AutoExpandChannelVidContainers || HQTN)
  519. {
  520. var lastCheckedURL = window.location.href;
  521. URLChanged(); //for initial page load
  522.  
  523. //poll for url changes
  524. setInterval(function(){
  525. if(lastCheckedURL != window.location.href)
  526. {
  527. lastCheckedURL = window.location.href;
  528. URLChanged();
  529. }
  530. }, 200);
  531. var waitForArrows, waitForSubsThumbnails;
  532. }
  533. /*============================================================*/
  534.  
  535. function AutoExpandContainers()
  536. {
  537. clearInterval(waitForArrows);
  538.  
  539. //=== clear potential old containers ===//
  540. let expandedEls = document.getElementsByClassName("expanded-wwc");
  541. //console.log("expanded els found: " + expandedEls.length);
  542. let numRemoved = 0;
  543.  
  544. //seems to always remove exactly half of them only, for some reason. So I guess do this until all have been removed
  545. while(expandedEls.length > 0)
  546. {
  547. for(let x = 0; x < expandedEls.length; x++)
  548. {
  549. if(!!expandedEls[x])
  550. {
  551. expandedEls[x].classList.remove("expanded-wwc");
  552. //console.log(++numRemoved + " cleared");
  553. }
  554. }
  555. expandedEls = document.getElementsByClassName("expanded-wwc");
  556. }
  557. //=== old containers cleared ===//
  558.  
  559. //=== unmark container arrows marked as clicked ===//
  560. numRemoved = 0;
  561. let clickedArrows = document.getElementsByClassName("clicked");
  562. //console.log("clicked found: " + clickedArrows.length);
  563. while(clickedArrows.length > 0)
  564. {
  565. for(let x = 0; x < clickedArrows.length; x++)
  566. {
  567. if(!!clickedArrows[x])
  568. {
  569. clickedArrows[x].classList.remove("clicked");
  570. //console.log(++numRemoved + " cleared");
  571. }
  572. }
  573. clickedArrows = document.getElementsByClassName("clicked");
  574. }
  575. //=== all arrows unmarked ===//
  576. //console.log("-expandedclear-");
  577.  
  578. //check that we are on a page that can have containers
  579. if(lastCheckedURL.includes("/user/") || lastCheckedURL.includes("/channel/") || lastCheckedURL.includes("/c/"))
  580. {
  581. //poll for untouched containers
  582. waitForArrows = setInterval(function(){
  583. //console.log("-searching...-");
  584. let arrowsRight = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #right-arrow > ytd-button-renderer.arrow");
  585. let arrowsLeft = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #left-arrow > ytd-button-renderer.arrow");
  586. if(!!arrowsRight && arrowsRight.length > 0 && !!arrowsLeft && arrowsLeft.length > 0)
  587. {
  588. //console.log("-found "+arrowsRight.length+"-");
  589. //do the thing for found untouched containers and mark them
  590. for(let i = 0; i < arrowsRight.length; i++)
  591. {
  592. if(!!arrowsRight[i] && arrowsRight[i].offsetParent !== null && !!arrowsLeft[i] && arrowsLeft[i].offsetParent !== null)
  593. {
  594. arrowsRight[i].parentElement.parentElement.classList.add("expanded-wwc");
  595. arrowsRight[i].click();
  596. //console.log("simulated click on right arrow");
  597. arrowsRight[i].classList.add("clicked");
  598. arrowsLeft[i].click();
  599. //console.log("simulated click on left arrow");
  600. arrowsLeft[i].classList.add("clicked");
  601. }
  602. }
  603. }
  604. }, 250);
  605. }
  606. }
  607.  
  608. function SwapSubsVidThumbnailsHQ()
  609. {
  610. clearInterval(waitForSubsThumbnails);
  611. if(lastCheckedURL.includes("/subscriptions") || lastCheckedURL.includes("/trending"))
  612. {
  613. waitForSubsThumbnails = setInterval(function(){
  614. let nails = document.querySelectorAll("img.yt-img-shadow[src*='hqdefault.jpg?']");
  615. //console.log("found " + nails.length + " LQ nails");
  616. for(let i = 0; i < nails.length; i++)
  617. nails[i].src = nails[i].src.split("?")[0];
  618. }, 200);
  619. }
  620. }
  621.  
  622. function URLChanged()
  623. {
  624. if(AutoExpandChannelVidContainers)
  625. AutoExpandContainers();
  626.  
  627. if(HQTN)
  628. SwapSubsVidThumbnailsHQ();
  629. }
  630. function CleanCSSValue(val)
  631. {
  632. val = val.trim();
  633.  
  634. //if only numbers...
  635. if(/^\d+$/.test(val))
  636. val += "px"; //...add px
  637.  
  638. return val;
  639. }
  640. function CleanNumber(val)
  641. {
  642. val = parseFloat(val);
  643.  
  644. return val;
  645. }
  646.  
  647. function addGlobalStyle(css)
  648. {
  649. var head, style;
  650. head = document.getElementsByTagName('head')[0];
  651. if (!head) { return; }
  652. style = document.createElement('style');
  653. style.type = 'text/css';
  654. style.innerHTML = css;
  655. head.appendChild(style);
  656. }
  657.  
  658. })();

QingJ © 2025

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