OpenGameArt Attribution Maker

Format the information from a content page

  1. // ==UserScript==
  2. // @name OpenGameArt Attribution Maker
  3. // @namespace http://poikilos.org/
  4. // @version 1.0.2
  5. // @description Format the information from a content page
  6. // @author Poikilos (Jake Gustafson)
  7. // @include https://opengameart.org/content/*
  8. // @grant none
  9. // @run-at document-end
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. // formerly @match https://opengameart.org/content/*
  14. var verbose = true;
  15.  
  16. var checkTimer = null;
  17. var submittedDateGrandParentClassName = "field-name-post-date";
  18. var authorAncestorClassName = "field-name-author-submitter"; // this div's children[1].firstChild.firstChild.firstChild is the author element
  19.  
  20. // var madeDivClassName = "username"; // <span class='username'> (may or may not contain <a>)
  21. var madeSpanClassName = "username"; // <span class='username'> (may or may not contain <a>)
  22. // ^ such as in `<span rel="sioc:has_creator"><a href="/users/reeguy" title="View user profile." class="username" xml:lang="" about="/users/reeguy" typeof="sioc:UserAccount" property="foaf:name" datatype="">reeguy</a></span><div class="field field-name-date-joined field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even"><small><em>joined 6 months 2 weeks ago</em></small></div></div></div><div class="field field-name-post-date field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even">02/10/2021 - 12:37</div></div></div> </div>`
  23. // ^ where other usernames may appear but the container span rel="sioc:has_creator" is unique.
  24. //var licenseClauseImgPrefix = "License__img";
  25. //var licenseAnchorPrefix = "License__link";
  26.  
  27.  
  28. // Find the URL and name such as in `<div class='license-icon'><a href='http://creativecommons.org/publicdomain/zero/1.0/' target='_blank'><img src='https://opengameart.org/sites/default/files/license_images/cc0.png' alt='' title=''><div class='license-name'>CC0`:
  29. var licenseAContainerClass = "license-icon";
  30. var licenseNameClass = "license-name";
  31. var collaboratorsClassName = "field-name-field-collaborators";
  32.  
  33. // var titlePrefix = "ThingPage__modelName";
  34. // var headingCreatedPrefix = "ThingPage__createdBy";
  35. // var doneDivPrefixes = [titlePrefix, headingCreatedPrefix];
  36. // var doneDivPrefixes = [madeDivClassName];
  37. // ^ This is only necessary when the page has lazy loading.
  38. // var clausesContainerPrefix = "License__ccLicense";
  39. var tagHrefContains = "field_art_tags_tid=";
  40. // var doneDivPrefixesMain = [clausesContainerPrefix];
  41. var doneClasses = [madeSpanClassName];
  42. var urlSmallNames = {
  43. "/by/1.0": "CC BY 1.0",
  44. "/by/2.0": "CC BY 2.0",
  45. "/by/2.5": "CC BY 2.5",
  46. "/by/3.0": "CC BY 3.0",
  47. "/by/4.0": "CC BY 4.0",
  48. "/by-sa/1.0": "CC BY-SA 1.0",
  49. "/by-sa/2.0": "CC BY-SA 2.0",
  50. "/by-sa/2.5": "CC BY-SA 2.5",
  51. "/by-sa/3.0": "CC BY-SA 3.0",
  52. "/by-sa/4.0": "CC BY-SA 4.0",
  53. "/by-nc/1.0": "CC BY-NC 1.0",
  54. "/by-nc/2.0": "CC BY-NC 2.0",
  55. "/by-nc/2.5": "CC BY-NC 2.5",
  56. "/by-nc/3.0": "CC BY-NC 3.0",
  57. "/by-nc/4.0": "CC BY-NC 4.0",
  58. "/by-nc-sa/1.0": "CC BY-NC-SA 1.0",
  59. "/by-nc-sa/2.0": "CC BY-NC-SA 2.0",
  60. "/by-nc-sa/2.5": "CC BY-NC-SA 2.5",
  61. "/by-nc-sa/3.0": "CC BY-NC-SA 3.0",
  62. "/by-nc-sa/4.0": "CC BY-NC-SA 4.0",
  63. "/by-nd/1.0": "CC BY-ND 1.0",
  64. "/by-nd/2.0": "CC BY-ND 2.0",
  65. "/by-nd/2.5": "CC BY-ND 2.5",
  66. "/by-nd/3.0": "CC BY-ND 3.0",
  67. "/by-nd/4.0": "CC BY-ND 4.0",
  68. "/by-nd-nc/1.0": "CC BY-ND-NC 1.0",
  69. "/by-nc-nd/2.0": "CC BY-NC-ND 2.0",
  70. "/by-nc-nd/2.5": "CC BY-NC-ND 2.5",
  71. "/by-nc-nd/3.0": "CC BY-NC-ND 3.0",
  72. "/by-nc-nd/4.0": "CC BY-NC-ND 4.0",
  73. "creativecommons.org/share-your-work/public-domain/cc0": "CC0",
  74. "creativecommons.org/publicdomain/zero/1.0": "CC0 1.0",
  75. };
  76. var bigNames = {
  77. "CC BY 1.0": "Creative Commons Attribution 1.0 Generic",
  78. "CC BY 2.0": "Creative Commons Attribution 2.0 Generic",
  79. "CC BY 2.5": "Creative Commons Attribution 2.5 Generic",
  80. "CC BY 3.0": "Creative Commons Attribution 3.0 Unported",
  81. "CC BY 4.0": "Creative Commons Attribution 4.0 International",
  82. "CC BY-SA 1.0": "Creative Commons Attribution-ShareAlike 1.0 Generic",
  83. "CC BY-SA 2.0": "Creative Commons Attribution-ShareAlike 2.0 Generic",
  84. "CC BY-SA 2.5": "Creative Commons Attribution-ShareAlike 2.5 Generic",
  85. "CC BY-SA 3.0": "Creative Commons Attribution-ShareAlike 3.0 Unported",
  86. "CC BY-SA 4.0": "Creative Commons Attribution-ShareAlike 4.0 International",
  87. "CC BY-NC 1.0": "Creative Commons Attribution-NonCommercial 1.0 Generic",
  88. "CC BY-NC 2.0": "Creative Commons Attribution-NonCommercial 2.0 Generic",
  89. "CC BY-NC 2.5": "Creative Commons Attribution-NonCommercial 2.5 Generic",
  90. "CC BY-NC 3.0": "Creative Commons Attribution-NonCommercial 3.0 Unported",
  91. "CC BY-NC 4.0": "Creative Commons Attribution-NonCommercial 4.0 International",
  92. "CC BY-NC-SA 1.0": "Creative Commons Attribution-NonCommercial-ShareAlike 1.0 Generic",
  93. "CC BY-NC-SA 2.0": "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Generic",
  94. "CC BY-NC-SA 2.5": "Creative Commons Attribution-NonCommercial-ShareAlike 2.5 Generic",
  95. "CC BY-NC-SA 3.0": "Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported",
  96. "CC BY-NC-SA 4.0": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
  97. "CC BY-ND 1.0": "Creative Commons Attribution-NoDerivs 1.0 Generic",
  98. "CC BY-ND 2.0": "Creative Commons Attribution-NoDerivs 2.0 Generic",
  99. "CC BY-ND 2.5": "Creative Commons Attribution-NoDerivs 2.5 Generic",
  100. "CC BY-ND 3.0": "Creative Commons Attribution-NoDerivs 3.0 Unported",
  101. "CC BY-ND 4.0": "Creative Commons Attribution-NoDerivatives 4.0 International",
  102. "CC BY-ND-NC 1.0": "Creative Commons Attribution-NoDerivs-NonCommercial 1.0 Generic",
  103. "CC BY-NC-ND 2.0": "Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Generic",
  104. "CC BY-NC-ND 2.5": "Creative Commons Attribution-NonCommercial-NoDerivs 2.5 Generic",
  105. "CC BY-NC-ND 3.0": "Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported",
  106. "CC BY-NC-ND 4.0": "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International",
  107. "CC0": "No Rights Reserved",
  108. "CC0 1.0": "Creative Commons CC0 1.0 Universal",
  109. };
  110. function getElementsWhereClassStartsWith(str) {
  111. if (verbose) {
  112. console.log("");
  113. console.log("getElementsWhereClassStartsWith(\""+str+"\")...");
  114. }
  115. var els = [];
  116. var all = document.getElementsByTagName("*");
  117. for (var i=0, max=all.length; i < max; i++) {
  118. var el = all[i];
  119. if (el.className.startsWith(str)) {
  120. els.push(el);
  121. }
  122. }
  123. if (verbose) {
  124. console.log("- FOUND " + els.length);
  125. }
  126. return els;
  127. }
  128.  
  129. function getElementsWhere(tagName, attributeName, value) {
  130. if (verbose) {
  131. console.log("");
  132. console.log("getSubElementsWhere(\""+tagName+"\", \""+attributeName+"\", \""+value+"\")...");
  133. }
  134. var els = [];
  135. var all = document.getElementsByTagName(tagName);
  136. for (var i=0, max=all.length; i < max; i++) {
  137. var el = all[i];
  138. if (el.getAttribute(attributeName) == value) {
  139. els.push(el);
  140. }
  141. }
  142. if (verbose) {
  143. console.log("- FOUND " + els.length);
  144. }
  145. return els;
  146. }
  147. function getDivsWhereClassStartsWith(str) {
  148. if (verbose) {
  149. console.log("");
  150. console.log("FIND getDivsWhereClassStartsWith(\"" + str + "\")...");
  151. }
  152. var els = [];
  153. var all = document.getElementsByTagName("div");
  154. for (var i=0, max=all.length; i < max; i++) {
  155. var el = all[i];
  156. if (el.className.startsWith(str)) {
  157. els.push(el);
  158. // console.log("- FOUND (" + els.length + ")");
  159. }
  160. else {
  161. // console.log("- " + el.className + " does not start with it.");
  162. }
  163. }
  164. if (verbose) {
  165. // console.log("Div count: " + all.length);
  166. console.log("- FOUND " + els.length);
  167. }
  168. return els;
  169. }
  170. function getWhereClassStartsWithIn(el, str) {
  171. if (el === undefined) {
  172. console.log("[getWhereClassStartsWithIn] Error: el is undefined.");
  173. return [];
  174. }
  175. if (verbose) {
  176. console.log("");
  177. console.log("DETECT getWhereClassStartsWithIn(el, \""+str+"\")...");
  178. // console.log(" el: " + JSON.stringify(el)); // DON'T do (could be circular)
  179. console.log(" el.className: "+el.className);
  180. console.log(" el.childNodes.length:"+el.childNodes.length+"...");
  181. }
  182. var els = [];
  183. var all = el.childNodes;
  184. for (var i=0, max=all.length; i < max; i++) {
  185. var thisEl = all[i];
  186. if (thisEl.className.startsWith(str)) {
  187. els.push(thisEl);
  188. // console.log("- FOUND");
  189. }
  190. else {
  191. // console.log("- "+el.className+" does not start with it.");
  192. }
  193. }
  194. if (verbose) {
  195. console.log("- FOUND " + els.length);
  196. // console.log("- done (div count: " + all.length + ")");
  197. }
  198. return els;
  199. }
  200. function hasAllDivPrefixes(prefixes) {
  201. var found = 0;
  202. for (var i=0, max=prefixes.length; i < max; i++) {
  203. if (getDivsWhereClassStartsWith(prefixes[i]).length > 0) {
  204. found++;
  205. }
  206. }
  207. return found >= prefixes.length;
  208. }
  209. function hasAllClasses(classNames) {
  210. var found = 0;
  211. for (var i=0, max=classNames.length; i < max; i++) {
  212. if (document.getElementsByClassName(classNames[i]).length > 0) {
  213. found++;
  214. }
  215. else {
  216. if (verbose) {
  217. console.error("The className " + classNames[i] + " was not found.")
  218. }
  219. }
  220. }
  221. return found >= classNames.length;
  222. }
  223. function elementHasAllPrefixes(el, prefixes) {
  224. var found = 0;
  225. for (var i=0, max=prefixes.length; i < max; i++) {
  226. if (getWhereClassStartsWithIn(el, prefixes[i]).length > 0) {
  227. found++;
  228. }
  229. }
  230. return found >= prefixes.length;
  231. }
  232. function getImgsWhereClassStartsWith(str) {
  233. var els = [];
  234. var all = document.images; // document.getElementsByTagName("img");
  235. for (var i=0, max=all.length; i < max; i++) {
  236. var el = all[i];
  237. if (el.className.startsWith(str)) {
  238. els.push(el);
  239. }
  240. }
  241. return els;
  242. }
  243. function getAnchorsWhereClassStartsWith(str) {
  244. if (verbose) {
  245. console.log("getAnchorsWhereClassStartsWith(\""+str+"\")...")
  246. }
  247. var els = [];
  248. var all = document.getElementsByTagName("a");
  249. for (var i=0, max=all.length; i < max; i++) {
  250. var el = all[i];
  251. if (el.className.startsWith(str)) {
  252. els.push(el);
  253. }
  254. }
  255. if (verbose) {
  256. console.log("- FOUND " + els.length);
  257. // console.log("- done (div count: " + all.length + ")");
  258. }
  259. return els;
  260. }
  261. function getAnchorsWhereHrefContains(str) {
  262. // Example: str=field_art_tags_tid= finds <a href="/art-search-advanced?field_art_tags_tid=grass">...
  263. if (verbose) {
  264. console.log("getAnchorsWhereHrefContains(\""+str+"\")...")
  265. }
  266. var els = [];
  267. var all = document.getElementsByTagName("a");
  268. for (var i=0, max=all.length; i < max; i++) {
  269. var el = all[i];
  270. if (el.href.includes(str)) {
  271. els.push(el);
  272. }
  273. }
  274. if (verbose) {
  275. console.log("- FOUND " + els.length);
  276. // console.log("- done (div count: " + all.length + ")");
  277. }
  278. return els;
  279. }
  280.  
  281. function elementAToMarkdown(element) {
  282. var ret = null;
  283. if (element.href) {
  284. ret = "[" + element.textContent + "](" + element.href + ")";
  285. }
  286. else {
  287. if (verbose) {
  288. console.warn("- elementAToMarkdown " + element.textContent + " href is blank in elementAToMarkdown: \"" + element.href + "\"")
  289. }
  290. ret = element.textContent;
  291. }
  292. return ret;
  293. }
  294.  
  295. function getMarkdown(info) {
  296. if (verbose) {
  297. console.log("");
  298. console.log("getMarkdown...");
  299. }
  300. var outputStr = "";
  301. if (info.title) {
  302. if (info.titleHref) {
  303. outputStr += "[" + info.title + "](" + info.titleHref + ")";
  304. }
  305. else {
  306. outputStr += "" + info.title;
  307. }
  308. outputStr += "\n";
  309. if (info.authorE) {
  310. outputStr += "\nAuthor: " + elementAToMarkdown(info.authorE);
  311. // + " and <insert contributor's name here>";
  312. outputStr += "\n";
  313. }
  314.  
  315. if (info.collaboratorElements) {
  316. outputStr += "\nCollaborators:"
  317. if (verbose) {
  318. console.log("Collaborators:");
  319. }
  320. var thisAuthorE = null;
  321. for (var i=0, max=info.collaboratorElements.length; i < max; i++) {
  322. thisAuthorE = info.collaboratorElements[i];
  323. if (verbose) {
  324. console.log(thisAuthorE.textContent, " ", thisAuthorE.href);
  325. }
  326. outputStr += "\n- " + elementAToMarkdown(thisAuthorE);
  327. }
  328. outputStr += "\n";
  329. }
  330. if (info.year) {
  331. if (info.submittedByE) {
  332. outputStr += "\n(Submitted by **" + elementAToMarkdown(info.submittedByE) + "**) ";
  333. }
  334. else {
  335. if (verbose) {
  336. console.warn("info.submittedByE is false"); // Do not try to read textContent or other properties since they don't exist!
  337. }
  338. outputStr += "\nPublished: ";
  339. }
  340. if (info.month) {
  341. outputStr += info.month + " ";
  342. if (info.day) {
  343. outputStr += info.day + ", "
  344. }
  345. }
  346. outputStr += info.year;
  347. if (info.hasOwnProperty("time")) {
  348. outputStr += " " + info.time;
  349. }
  350. outputStr += "\n";
  351. }
  352. }
  353. if (info.licenses) {
  354. outputStr += "\nLicense(s):";
  355. var licenseE = null;
  356. var license = null;
  357. for (i=0, max=info.licenses.length; i < max; i++) {
  358. licenseE = info.licenses[i];
  359. license = {};
  360. license.href = licenseE.href;
  361. license.shortLicense = licenseE.shortLicense;
  362. license.textContent = licenseE.longName;
  363. if (licenseE.shortLicense) {
  364. license.textContent = licenseE.shortLicense; // Display the short license name if present.
  365. }
  366. outputStr += "\n- " + elementAToMarkdown(license);
  367. }
  368. outputStr += "\n";
  369. }
  370. else {
  371. outputStr += "\nLICENSE: [insert license name (&URL unless in each content ZIP) from the original here]\n";
  372. }
  373. var tagAnchors = getAnchorsWhereHrefContains(tagHrefContains);
  374. var tai;
  375. if (tagAnchors.length > 0) {
  376. outputStr += "\nTags:";
  377. for (tai = 0; tai < tagAnchors.length; tai++) {
  378. var tagA = tagAnchors[tai];
  379. outputStr += "\n- [" + tagA.textContent + "](" + tagA.href + ")";
  380. }
  381. outputStr += "\n";
  382. }
  383. else {
  384. console.error("The page had no tags ('a' tags with *"+tagHrefContains+"* href)")
  385. }
  386.  
  387. if (info.attributionNotice) {
  388. outputStr += "\n## " + info.goodAttributionNoticeFlag + "\n" + info.attributionNotice + "\n";
  389. }
  390.  
  391. return outputStr;
  392. }
  393.  
  394. function populateCorrespondingLicenseFields(license) {
  395. var licenseShortStr = "";
  396. license.longName = license.textContent; // Store longName separately so it can be edited without modifying the page!
  397. if (license) {
  398. var versionIsFound = false;
  399. var licenseLower = license.textContent.toLowerCase();
  400. if (license.textContent.startsWith("Creative Commons") || license.textContent.startsWith("CC")) {
  401. if (license.textContent.startsWith("CC0 1.0") || license.textContent.startsWith("Creative Commons 0 1.0") || license.textContent.startsWith("Creative Commons Zero 1.0")) {
  402. if (!license.href) {
  403. license.href = "https://creativecommons.org/publicdomain/zero/1.0/";
  404. }
  405. licenseShortStr = "CCO 1.0";
  406. }
  407. else if ((license.textContent == "Creative Commons 0") || (license.textContent == "Creative Commons Zero")) {
  408. licenseShortStr = "CCO";
  409. }
  410. else {
  411. console.log("Looking for license clauses in license name \""+licenseLower+"\"...");
  412. licenseShortStr = "CC ";
  413. if (licenseLower.includes("attribution")) {
  414. licenseShortStr += "BY";
  415. }
  416. if (licenseLower.includes("non-commercial") || licenseLower.includes("noncommercial") || licenseLower.includes("non commercial")) {
  417. licenseShortStr += "-NC";
  418. }
  419. if (licenseLower.includes("no derivatives") || licenseLower.includes("noderivs") || licenseLower.includes("no-derivatives") || licenseLower.includes("noderivatives")) {
  420. licenseShortStr += "-ND";
  421. }
  422. if (licenseLower.includes("sharealike") || licenseLower.includes("share-alike") || licenseLower.includes("share alike") ) {
  423. licenseShortStr += "-SA";
  424. }
  425.  
  426. if (license.textContent.includes("1.0")) {
  427. licenseShortStr += " 1.0";
  428. versionIsFound = true;
  429. }
  430. else if (license.textContent.includes("2.0")) {
  431. licenseShortStr += " 2.0";
  432. versionIsFound = true;
  433. }
  434. else if (license.textContent.includes("3.0")) {
  435. licenseShortStr += " 3.0";
  436. versionIsFound = true;
  437. }
  438. else if (license.textContent.includes("4.0")) {
  439. licenseShortStr += " 4.0";
  440. versionIsFound = true;
  441. }
  442. else if (license.exactLicenseVersion !== null) {
  443. licenseShortStr += " " + license.exactLicenseVersion;
  444. versionIsFound = true;
  445. }
  446. }
  447. }
  448. console.log("licenseShortStr: " + licenseShortStr);
  449. if (!license.href) {
  450. var parts = licenseShortStr.split(" ");
  451. if (parts.length == 3) {
  452. var partialHref = null;
  453. // such as ["CC", "BY-SA", "3.0"]
  454. if (parts[1] == "BY") {
  455. partialHref = "http://creativecommons.org/licenses/by/";
  456. }
  457. else if (parts[1] == "BY-SA") {
  458. partialHref = "http://creativecommons.org/licenses/by-sa/";
  459. }
  460. else if (parts[1] == "BY-NC-SA") {
  461. partialHref = "http://creativecommons.org/licenses/by-nc-sa/";
  462. }
  463. else if (parts[1] == "BY-NC-ND") {
  464. partialHref = "http://creativecommons.org/licenses/by-nc-nd/";
  465. }
  466. // NOTE: by-nc-nd-sa is NOT a valid license
  467. if (partialHref != null) {
  468. license.href = partialHref + parts[2] + "/";
  469. }
  470. }
  471. }
  472. }
  473. else if (license.href) {
  474. if (!licenseShortStr) {
  475. if (verbose) {
  476. console.log("Generating short license name from URL instead of from clauses...");
  477. }
  478. for (var key in urlSmallNames) {
  479. // Check if the property/key is defined in the object itself, not in parent
  480. if (urlSmallNames.hasOwnProperty(key)) {
  481. if (license.href.includes(key)) {
  482. licenseShortStr = urlSmallNames[key];
  483. if (verbose) {
  484. console.log("- got \""+licenseShortStr+"\" from \""+key+"\"")
  485. }
  486. break;
  487. }
  488. }
  489. }
  490. }
  491. else {
  492. console.log("* using existing licenseShortStr \""+licenseShortStr+"\"");
  493. }
  494.  
  495. if (!licenseShortStr) {
  496. console.warn("Warning: The URL \""+license.href+"\" is not recognized (No key in Thing Remix Attribution Maker's urlSmallNames is a partial of the URL), so the long license name could not be generated.");
  497. }
  498. else {
  499. info.shortLicense = licenseShortStr;
  500. if (!license.textContent) {
  501. if (verbose) {
  502. console.log("Generating license longName from URL instead of from clauses...");
  503. }
  504. if (bigNames.hasOwnProperty(licenseShortStr)) {
  505. // ^ The clauses are only in this order for versions above 1.0!
  506. license.longName = bigNames[licenseShortStr];
  507. if (verbose) {
  508. console.log("- got \""+info.longName+"\"");
  509. }
  510. }
  511. else {
  512. console.warn("Warning: The short license name \""+licenseShortStr+"\" is not recognized (It is not a key in Thing Remix Attribution Maker's bigNames), so the long license name could not be generated.");
  513. }
  514. }
  515. }
  516. }
  517. if (!license.textContent) {
  518. console.warn("The license abbreviation cannot be generated because no license text was generated (no license elements were detected).");
  519. }
  520. else {
  521. console.warn("The license abbreviation cannot be generated for an unknown license: " + license.textContent);
  522. }
  523. }
  524.  
  525. function setClipboardText(text, callbackBtn) {
  526. var msg = "(ERROR: Your browser API is unknown.)";
  527. var okMsg = " &#10003;";
  528. // See https://stackoverflow.com/questions/52177405/clipboard-writetext-doesnt-work-on-mozilla-ie
  529. if (navigator.clipboard != undefined) { // Chrome
  530. navigator.clipboard.writeText(text).then(
  531. function () {
  532. console.log('Async: Copying to clipboard was successful!');
  533. callbackBtn.innerHTML += okMsg;
  534. }, function (err) {
  535. console.error('Async: Could not copy text: ', err);
  536. callbackBtn.innerHTML += '<br/> (ERROR: Accessing the clipboard failed.)';
  537. }
  538. );
  539. msg = null;
  540. }
  541. else if (window.clipboardData) { // Internet Explorer
  542. window.clipboardData.setData("Text", text);
  543. msg = okMsg;
  544. }
  545. if (msg != null) {
  546. callbackBtn.innerHTML += msg;
  547. }
  548. }
  549.  
  550. function getButtonContainer() {
  551. // var pageInfoEs = document.getElementsByClassName("item-page-info");
  552. var pageInfoEs = getElementsWhereClassStartsWith(madeSpanClassName);
  553. if (pageInfoEs.length < 1) {
  554. return null;
  555. }
  556. return pageInfoEs[0];
  557. }
  558.  
  559. function getInfo() {
  560. 'use strict';
  561. var info = {};
  562. // There should only be one.
  563. // pageInfoE.innerHTML += "<button onclick=\"getRemixLicense()\">Copy Markdown</button>";
  564. // var licenseTextE = document.getElementsByClassName("license-text");
  565. // var licenseTextE = getDivsWhereClassStartsWith(clausesContainerPrefix);
  566. // var pageInfoEs = document.getElementsByClassName("item-page-info");
  567. // var pageInfoEs = getDivsWhereClassStartsWith(madeDivClassName);
  568. // console.log("Checking "+madeDivClassName+"* elements: " + JSON.stringify(pageInfoEs));
  569. var titleH2ParentElements = getElementsWhere("div", "property", "dc:title"); // var headingParts = getDivsWhereClassStartsWith(titlePrefix);
  570. if (titleH2ParentElements.length > 0) {
  571. info.title = titleH2ParentElements[0].firstChild.textContent; // "<div ...><h2>Title..."
  572. }
  573. else {
  574. console.warn("The title is missing. There are no divs with a class starting with " + titlePrefix);
  575. }
  576.  
  577. var authorAndSubmitterDivs = document.getElementsByClassName(authorAncestorClassName);
  578. var collaboratorElements = [];
  579. if (authorAndSubmitterDivs.length > 0) {
  580. var goodAuthorFlag = "Author:";
  581. if (!authorAndSubmitterDivs[0].children[0].textContent.includes(goodAuthorFlag)) {
  582. console.warn("The first child of div class " + authorAncestorClassName + " should include \"" + goodAuthorFlag + "\" but is \"" + authorAndSubmitterDivs[0].children[0].textContent + "\"");
  583. }
  584. var authorE = authorAndSubmitterDivs[0].children[1].firstChild.firstChild.firstChild;
  585. // ^ such as <div class="field field-name-author-submitter field-type-ds field-label-above">
  586. // <div class="field-label">Author:&nbsp;</div>
  587. // <div class="field-items"> <!--children[1]-->
  588. // <div class="field-item even"> <!--.firstChild-->
  589. // <span class='username'> <!--.firstChild-->
  590. // <a href='http://3tdstudios.com/' target='_blank'>Ron Kapaun</a>
  591. // </span>
  592. // <br/>(Submitted by <strong><a href="/users/hreikin">hreikin</a></strong>)</div></div></div><div class="field field-name-post-date field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even">Thursday, November 6, 2014 - 13:08</div></div></div><div class="field field-name-field-art-type field-type-taxonomy-term-reference field-label-above"><div class="field-label">Art Type:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/art-search-advanced?field_art_type_tid%5B%5D=10" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">3D Art</a></div></div></div><div class="field field-name-field-art-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=torque" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">torque</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=dae" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">dae</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=furniture" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">furniture</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=bookshelf" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">bookshelf</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=china" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">china</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=hutch" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">hutch</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=cupboard" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">cupboard</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=Desk" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Desk</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=table" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">table</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=end%20table" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">end table</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=square" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">square</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=workbench" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">workbench</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=prop" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">prop</a></div></div></div><div class="field field-name-field-art-licenses field-type-taxonomy-term-reference field-label-above"><div class="field-label">License(s):&nbsp;</div><div class="field-items"><div class="field-item even"><div class='license-icon'><a href='http://creativecommons.org/publicdomain/zero/1.0/' target='_blank'><img src='https://opengameart.org/sites/default/files/license_images/cc0.png' alt='' title=''><div class='license-name'>CC0</div></a></div></div></div></div><div class="field field-name-collect field-type-ds field-label-above"><div class="field-label">Collections:&nbsp;</div><div class="field-items"><div class="field-item even"><div class='collect-container'><ul><li><a href="/content/3d-packs">3D - Packs</a></li><li><a href="/content/3d-furniture-and-other-interiorexterior-decorables-under-cc0">3D Furniture and other interior/Exterior Decorables under CC0</a></li><li><a href="/content/3d-medieval-fantasy">3D Medieval Fantasy</a></li><li><a href="/content/3d-models">3D Models</a></li><li><a href="/content/3d-stuff-thangs">3D Stuff &amp; thangs</a></li><li><a href="/content/3td-studios-packs">3TD Studios Packs</a></li><li><a href="/content/arce-movens-2">Arce Movens 2</a></li><li><a href="/content/cc0-assets">CC0 Assets</a></li><li><a href="/content/cc0-assets-3d-low-poly">CC0 ASSETS 3D LOW POLY</a></li><li><a href="/content/cc0-furniture">CC0 Furniture</a></li><li><a href="/content/cco-3d-furniture">CCO 3D Furniture</a></li><li><a href="/content/dead-welcoming">Dead Welcoming</a></li><li><a href="/content/deco">Deco</a></li><li><a href="/content/freerpg-project-assets">FreeRPG Project Assets</a></li><li><a href="/content/game-project-models">Game Project Models</a></li><li><a href="/content/hq-items-interior">HQ Items Interior</a></li><li><a href="/content/legend-of-rathnor-parts">Legend of Rathnor Parts</a></li><li><a href="/content/low-poly-1">low poly</a></li><li><a href="/content/lr">LR</a></li><li><a href="/content/mysterious-sprites-and-housemansion-parts">Mysterious Sprites and House/Mansion Parts</a></li><li><a href="/content/openmw-showcase-possibilities">OpenMW showcase possibilities</a></li><li><a href="/content/torque3d-possible-modelstextures">Torque3D possible models/textures</a></li><li><a href="/content/turodas">Turodas</a></li></ul></div></div></div></div><div class="field field-name-favorites field-type-ds field-label-inline clearfix"><div class="field-label">Favorites:&nbsp;</div><div class="field-items"><div class="field-item even">23</div></div></div><div class="field field-name-flag-favorite field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even"><span class="flag-wrapper flag-favorites flag-favorites-30816">
  593. // collaboratorElements.push(authorE);
  594. if (authorAndSubmitterDivs[0].children[1].firstChild.children[2]) {
  595. var textAfterBRNode = authorAndSubmitterDivs[0].children[1].firstChild.childNodes[2];
  596. // ^ INFO: authorAndSubmitterDivs[0].children[1].firstChild.children[1].textContent is "" because a <br/> doesn't have textContent.
  597. if (verbose) {
  598. // console.log("author + opener for submitter: " + authorAndSubmitterDivs[0].children[1].firstChild.textContent);
  599. console.log("A submitter opener was found: \"" + textAfterBRNode.textContent + "\"");
  600. }
  601. if (textAfterBRNode.textContent.includes("Submitted by")) {
  602. var submittedByE = authorAndSubmitterDivs[0].children[1].firstChild.children[2].firstChild; // children[1] is field-items . firstChild is field-item even . children[2] is <strong> . firstChild is <a ...>
  603. if (verbose) {
  604. console.log("Submitted by:", submittedByE.textContent, "href=" + submittedByE.href)
  605. }
  606. info.submittedByE = submittedByE;
  607. }
  608. else {
  609. if (verbose) {
  610. console.log("There is no \"Submitted by\" in the", authorAncestorClassName, "children[1].firstChild.children[2]")
  611. }
  612. }
  613. }
  614. if (verbose) {
  615. console.log("author: " + authorE.textContent, "href:", authorE.href);
  616. }
  617. // console.warn("Multiple authors (collaboratorElements) is not yet implemented.");
  618. info.authorE = authorE;
  619. }
  620. else {
  621. console.warn("The author is missing. There are no divs with a class " + authorAncestorClassName + " having a great grandchild of the second child");
  622. }
  623.  
  624. var collaboratorDivs = document.getElementsByClassName(collaboratorsClassName);
  625. if (collaboratorDivs.length > 0) {
  626. info.collaboratorElements = collaboratorElements;
  627. var goodCollaboratorsFlag = "Collaborators:";
  628. if (collaboratorDivs[0].children.length >= 2) {
  629. if (!collaboratorDivs[0].children[0].textContent.includes(goodCollaboratorsFlag)) {
  630. console.warn("The first child of div class " + collaboratorsClassName + " does not say \"" + goodCollaboratorsFlag + "\"");
  631. }
  632. var collaboratorsContainerE = collaboratorDivs[0].children[1];
  633. var thisAuthorE = {};
  634. for (var i=0, max=collaboratorsContainerE.children.length; i < max; i++) {
  635. thisAuthorE = collaboratorsContainerE.children[i].firstChild; //firstChild of the <div ...> is <a ...>
  636. //var tmpAuthorObj = {};
  637. //tmpAuthorObj.textContent = thisAuthorE.textContent;
  638. //tmpAuthorObj.href = thisAuthorE.href; // TODO: Why is this necessary (href is blank during iteration otherwise)?
  639. if (verbose) {
  640. if (!thisAuthorE.href) {
  641. console.warn("- collaborator " + thisAuthorE.textContent + " href is blank in addButton: \"" + thisAuthorE.href + "\"")
  642. }
  643. // else {
  644. // console.warn("- collaborator " + thisAuthorE.textContent + " href is non-blank in addButton: \"" + thisAuthorE.href + "\"")
  645. // }
  646. }
  647. info.collaboratorElements.push(thisAuthorE);
  648. }
  649. }
  650. else {
  651. console.warn("div class " + collaboratorsClassName + " should have 2 children but has " + collaboratorDivs[0].children.length + ".");
  652. }
  653. }
  654. // ^ Such as in <div class="field field-name-field-collaborators field-type-user-reference field-label-above">
  655. // <div class="field-label">Collaborators:&nbsp;</div>
  656. // <div class="field-items">
  657. // <div class="field-item even"><a href="/users/daneeklu">daneeklu</a></div>
  658. // <div class="field-item odd"><a href="/users/jetrel">Jetrel</a></div>
  659. // <div class="field-item even"><a href="/users/hyptosis">Hyptosis</a></div>
  660. // <div class="field-item odd"><a href="/users/redshrike">Redshrike</a></div>
  661. // <div class="field-item even"><a href="/users/bertram">Bertram</a></div></div>
  662. // </div>
  663.  
  664. // TODO: add artTypeStr
  665. // ^ Such as in <div class="field field-name-field-art-type field-type-taxonomy-term-reference field-label-above">
  666. // <div class="field-label">Art Type:&nbsp;</div>
  667. // <div class="field-items">
  668. // <div class="field-item even"><a href="/art-search-advanced?field_art_type_tid%5B%5D=9" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">2D Art</a></div></div></div><div class="field field-name-field-art-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=RPG" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">RPG</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=tiles" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">tiles</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=32x32" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">32x32</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=food" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">food</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=Wood" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Wood</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=Market%20Booth" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Market Booth</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=grass" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">grass</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=water" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">water</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=path" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">path</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=cobblestone" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">cobblestone</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=firewood" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">firewood</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=table" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">table</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=dock" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">dock</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=boat" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">boat</a></div></div></div><div class="field field-name-field-art-licenses field-type-taxonomy-term-reference field-label-above"><div class="field-label">License(s):&nbsp;</div><div class="field-items"><div class="field-item even"><div class='license-icon'><a href='http://creativecommons.org/licenses/by-sa/3.0/' target='_blank'><img src='https://opengameart.org/sites/default/files/license_images/cc-by-sa.png' alt='' title=''><div class='license-name'>CC-BY-SA 3.0</div></a></div></div></div></div><div class="field field-name-collect field-type-ds field-label-above"><div class="field-label">Collections:&nbsp;</div><div class="field-items"><div class="field-item even"><div class='collect-container'><ul><li><a href="/content/04-pixel-art-terrain">04. Pixel Art - Terrain</a></li><li><a href="/content/2-acetoxy-nnn-trimethylethanaminium">2-Acetoxy-N,N,N-trimethylethanaminium</a></li><li><a href="/content/2d-rpg-lpc-compatible-tilessprites">2D - RPG - [LPC]-Compatible Tiles/Sprites</a></li><li><a href="/content/2d-32x32">2D 32x32</a></li><li><a href="/content/2d-tilesets-topview">2D tilesets topview</a></li><li><a href="/content/2dtileorthogonal">2D::Tile::Orthogonal</a></li><li><a href="/content/32x32-fantasy-tiles">32x32 Fantasy Tiles</a></li><li><a href="/content/acid">Acid</a></li><li><a href="/content/andruil-rpg">Andruil RPG</a></li><li><a href="/content/art-used-in-dusk-graphical-mud">Art used in Dusk Graphical MUD</a></li><li><a href="/content/assets-for-planned-use-in-realm-of-kuhraiy">Assets for Planned Use in Realm of Kuhraiy</a></li><li><a href="/content/awesome-game-art">Awesome Game Art</a></li><li><a href="/content/backgrounds-6">BACKGROUNDS</a></li><li><a href="/content/base-pixel-art-for-3d-pixelish-rpg">Base pixel art for 3D pixelish RPG</a></li><li><a href="/content/besidethevoids-downloads">BesideTheVoid&#039;s Downloads</a> (<a href="/collect/remove/14914/85607" class="collect-remove">remove</a>)</li><li><a href="/content/best-orthogonal-rectangular-tilesets-for-tilemaps">Best Orthogonal (rectangular) Tilesets for Tilemaps</a></li><li><a href="/content/bits-and-bobs">Bits and Bobs</a></li><li><a href="/content/bunchofheroes">BunchOfHeroes</a></li><li><a href="/content/c-dogs-sdl-art">C-Dogs SDL art</a></li><li><a href="/content/conquest-rpg-assets">Conquest RPG Assets</a></li><li><a href="/content/credits-0">Credits</a></li><li><a href="/content/ctf">CTF</a></li><li><a href="/content/dungeon-slayer-art">Dungeon Slayer Art</a></li><li><a href="/content/fantasy-6">Fantasy</a></li><li><a href="/content/field-guardians">Field Guardians</a></li><li><a href="/content/game-prototype-art-assets">Game Prototype Art Assets </a></li><li><a href="/content/gamecollection">GameCollection</a></li><li><a href="/content/golden-axe">Golden Axe</a></li><li><a href="/content/hero-game">hero game</a></li><li><a href="/content/hq-2d-isometric">HQ 2D &amp; Isometric</a></li><li><a href="/content/infinimon-procedurally-generated-pokemon-or-digimon-style-game-assets">Infinimon - Procedurally-Generated Pokemon- or Digimon-style Game Assets</a></li><li><a href="/content/liberated-pixel-cup-0">Liberated Pixel Cup</a></li><li><a href="/content/long-licence-fantasy-modern-game">long licence fantasy modern game</a></li><li><a href="/content/loot-run">Loot run</a></li><li><a href="/content/lpc-1">LPC</a></li><li><a href="/content/lpc-compatible-terraintiles">LPC Compatible Terrain/Tiles</a></li><li><a href="/content/lpc-gfx">LPC GFX</a></li><li><a href="/content/maybe-assets-for-treasure-other">maybe assets for Treasure (+other)</a></li><li><a href="/content/medicines-disordered-list-of-fantasy-rpg-tilesets">Medicine&#039;s disordered list of Fantasy RPG Tilesets</a></li><li><a href="/content/minimmo-project">Minimmo project</a></li><li><a href="/content/mittys-maize">Mitty&#039;s Maize</a></li><li><a href="/content/must-use">Must Use</a></li><li><a href="/content/non-commercial-art">Non-Commercial - Art</a></li><li><a href="/content/oddball-gamez-lpc-style">Oddball Gamez LPC Style</a></li><li><a href="/content/one-click-minecraft">one click minecraft</a></li><li><a href="/content/pixelfarm">PixelFarm</a></li><li><a href="/content/roguelike">Roguelike</a></li><li><a href="/content/rpg-2">RPG</a></li><li><a href="/content/rpg-5">RPG</a></li><li><a href="/content/rpg-stuff-collection">RPG Stuff Collection</a></li><li><a href="/content/sets">SETS</a></li><li><a href="/content/smartpoints-example-game">SmartPoints Example Game</a></li><li><a href="/content/snes-style-rpg">SNES Style RPG</a></li><li><a href="/content/snes-like-world-textures">snes-like world textures</a></li><li><a href="/content/sprites-2">Sprites</a></li><li><a href="/content/stardont">stardont</a></li><li><a href="/content/stendhal">Stendhal</a></li><li><a href="/content/terrain-transitions">Terrain transitions</a></li><li><a href="/content/test-10">test</a></li><li><a href="/content/test-5">Test</a></li><li><a href="/content/test-11">test</a></li><li><a href="/content/the-weary-adventurer">The Weary Adventurer</a></li><li><a href="/content/thing">Thing</a></li><li><a href="/content/tile-4">TILE</a></li><li><a href="/content/tilesets-and-backgrounds-pixelart">Tilesets and Backgrounds (PixelArt)</a></li><li><a href="/content/top-down-2d-jrpg-32x32-art-collection">Top Down 2D JRPG 32x32 Art Collection</a></li><li><a href="/content/top-down-rpg-pixel-art">Top Down RPG Pixel Art</a></li><li><a href="/content/top-down-2d-rpg">Top-down 2D RPG</a></li><li><a href="/content/topdown-tiles">topdown tiles</a></li><li><a href="/content/trevas">Trevas</a></li><li><a href="/content/ultimate-tabletop">Ultimate TableTop</a></li><li><a href="/content/used-in-hero-of-allacrost">Used in Hero of Allacrost</a></li><li><a href="/content/used-in-valyria-tear">Used in Valyria tear</a></li><li><a href="/content/wastelander">Wastelander</a></li><li><a href="/content/workable-style-32x32-tiles">Workable style 32x32 tiles</a></li><li><a href="/content/zed-interesting-yet-unsorted">Zed - Interesting Yet Unsorted</a></li><li><a href="/content/zelda-like-rpg">Zelda Like RPG</a></li><li><a href="/content/zombie-buster-project">zombie-buster project</a></li></ul></div></div></div></div><div class="field field-name-favorites field-type-ds field-label-inline clearfix"><div class="field-label">Favorites:&nbsp;</div><div class="field-items"><div class="field-item even">235</div></div></div><div class="field field-name-flag-favorite field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even"><span class="flag-wrapper flag-favorites flag-favorites-14914">
  669.  
  670. var submittedDateStr = null; // formerly createdStr
  671. // var headingCreatedParts = getDivsWhereClassStartsWith(headingCreatedPrefix);
  672. var submittedDateDivs = document.getElementsByClassName(submittedDateGrandParentClassName);
  673. if (submittedDateDivs.length > 0) {
  674. var submittedDateE = submittedDateDivs[0].firstChild.firstChild;
  675. submittedDateStr = submittedDateE.textContent;
  676. // ^ such as in <div class="field field-name-post-date field-type-ds field-label-hidden">
  677. // <div class="field-items"> <!--.firstChild-->
  678. // <div class="field-item even">Thursday, January 31, 2013 - 08:06</div></div></div><div class="field field-name-field-collaborators field-type-user-reference field-label-above"><div class="field-label">Collaborators:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/users/daneeklu">daneeklu</a></div><div class="field-item odd"><a href="/users/jetrel">Jetrel</a></div><div class="field-item even"><a href="/users/hyptosis">Hyptosis</a></div><div class="field-item odd"><a href="/users/redshrike">Redshrike</a></div><div class="field-item even"><a href="/users/bertram">Bertram</a></div></div></div><div class="field field-name-field-art-type field-type-taxonomy-term-reference field-label-above"><div class="field-label">Art Type:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/art-search-advanced?field_art_type_tid%5B%5D=9" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">2D Art</a></div></div></div><div class="field field-name-field-art-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=RPG" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">RPG</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=tiles" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">tiles</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=32x32" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">32x32</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=food" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">food</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=Wood" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Wood</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=Market%20Booth" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Market Booth</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=grass" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">grass</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=water" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">water</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=path" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">path</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=cobblestone" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">cobblestone</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=firewood" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">firewood</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=table" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">table</a></div><div class="field-item even"><a href="/art-search-advanced?field_art_tags_tid=dock" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">dock</a></div><div class="field-item odd"><a href="/art-search-advanced?field_art_tags_tid=boat" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">boat</a></div></div></div><div class="field field-name-field-art-licenses field-type-taxonomy-term-reference field-label-above"><div class="field-label">License(s):&nbsp;</div><div class="field-items"><div class="field-item even"><div class='license-icon'><a href='http://creativecommons.org/licenses/by-sa/3.0/' target='_blank'><img src='https://opengameart.org/sites/default/files/license_images/cc-by-sa.png' alt='' title=''><div class='license-name'>CC-BY-SA 3.0</div></a></div></div></div></div><div class="field field-name-collect field-type-ds field-label-above"><div class="field-label">Collections:&nbsp;</div><div class="field-items"><div class="field-item even"><div class='collect-container'><ul><li><a href="/content/04-pixel-art-terrain">04. Pixel Art - Terrain</a></li><li><a href="/content/2-acetoxy-nnn-trimethylethanaminium">2-Acetoxy-N,N,N-trimethylethanaminium</a></li><li><a href="/content/2d-rpg-lpc-compatible-tilessprites">2D - RPG - [LPC]-Compatible Tiles/Sprites</a></li><li><a href="/content/2d-32x32">2D 32x32</a></li><li><a href="/content/2d-tilesets-topview">2D tilesets topview</a></li><li><a href="/content/2dtileorthogonal">2D::Tile::Orthogonal</a></li><li><a href="/content/32x32-fantasy-tiles">32x32 Fantasy Tiles</a></li><li><a href="/content/acid">Acid</a></li><li><a href="/content/andruil-rpg">Andruil RPG</a></li><li><a href="/content/art-used-in-dusk-graphical-mud">Art used in Dusk Graphical MUD</a></li><li><a href="/content/assets-for-planned-use-in-realm-of-kuhraiy">Assets for Planned Use in Realm of Kuhraiy</a></li><li><a href="/content/awesome-game-art">Awesome Game Art</a></li><li><a href="/content/backgrounds-6">BACKGROUNDS</a></li><li><a href="/content/base-pixel-art-for-3d-pixelish-rpg">Base pixel art for 3D pixelish RPG</a></li><li><a href="/content/besidethevoids-downloads">BesideTheVoid&#039;s Downloads</a> (<a href="/collect/remove/14914/85607" class="collect-remove">remove</a>)</li><li><a href="/content/best-orthogonal-rectangular-tilesets-for-tilemaps">Best Orthogonal (rectangular) Tilesets for Tilemaps</a></li><li><a href="/content/bits-and-bobs">Bits and Bobs</a></li><li><a href="/content/bunchofheroes">BunchOfHeroes</a></li><li><a href="/content/c-dogs-sdl-art">C-Dogs SDL art</a></li><li><a href="/content/conquest-rpg-assets">Conquest RPG Assets</a></li><li><a href="/content/credits-0">Credits</a></li><li><a href="/content/ctf">CTF</a></li><li><a href="/content/dungeon-slayer-art">Dungeon Slayer Art</a></li><li><a href="/content/fantasy-6">Fantasy</a></li><li><a href="/content/field-guardians">Field Guardians</a></li><li><a href="/content/game-prototype-art-assets">Game Prototype Art Assets </a></li><li><a href="/content/gamecollection">GameCollection</a></li><li><a href="/content/golden-axe">Golden Axe</a></li><li><a href="/content/hero-game">hero game</a></li><li><a href="/content/hq-2d-isometric">HQ 2D &amp; Isometric</a></li><li><a href="/content/infinimon-procedurally-generated-pokemon-or-digimon-style-game-assets">Infinimon - Procedurally-Generated Pokemon- or Digimon-style Game Assets</a></li><li><a href="/content/liberated-pixel-cup-0">Liberated Pixel Cup</a></li><li><a href="/content/long-licence-fantasy-modern-game">long licence fantasy modern game</a></li><li><a href="/content/loot-run">Loot run</a></li><li><a href="/content/lpc-1">LPC</a></li><li><a href="/content/lpc-compatible-terraintiles">LPC Compatible Terrain/Tiles</a></li><li><a href="/content/lpc-gfx">LPC GFX</a></li><li><a href="/content/maybe-assets-for-treasure-other">maybe assets for Treasure (+other)</a></li><li><a href="/content/medicines-disordered-list-of-fantasy-rpg-tilesets">Medicine&#039;s disordered list of Fantasy RPG Tilesets</a></li><li><a href="/content/minimmo-project">Minimmo project</a></li><li><a href="/content/mittys-maize">Mitty&#039;s Maize</a></li><li><a href="/content/must-use">Must Use</a></li><li><a href="/content/non-commercial-art">Non-Commercial - Art</a></li><li><a href="/content/oddball-gamez-lpc-style">Oddball Gamez LPC Style</a></li><li><a href="/content/one-click-minecraft">one click minecraft</a></li><li><a href="/content/pixelfarm">PixelFarm</a></li><li><a href="/content/roguelike">Roguelike</a></li><li><a href="/content/rpg-2">RPG</a></li><li><a href="/content/rpg-5">RPG</a></li><li><a href="/content/rpg-stuff-collection">RPG Stuff Collection</a></li><li><a href="/content/sets">SETS</a></li><li><a href="/content/smartpoints-example-game">SmartPoints Example Game</a></li><li><a href="/content/snes-style-rpg">SNES Style RPG</a></li><li><a href="/content/snes-like-world-textures">snes-like world textures</a></li><li><a href="/content/sprites-2">Sprites</a></li><li><a href="/content/stardont">stardont</a></li><li><a href="/content/stendhal">Stendhal</a></li><li><a href="/content/terrain-transitions">Terrain transitions</a></li><li><a href="/content/test-10">test</a></li><li><a href="/content/test-11">test</a></li><li><a href="/content/test-5">Test</a></li><li><a href="/content/the-weary-adventurer">The Weary Adventurer</a></li><li><a href="/content/thing">Thing</a></li><li><a href="/content/tile-4">TILE</a></li><li><a href="/content/tilesets-and-backgrounds-pixelart">Tilesets and Backgrounds (PixelArt)</a></li><li><a href="/content/top-down-2d-jrpg-32x32-art-collection">Top Down 2D JRPG 32x32 Art Collection</a></li><li><a href="/content/top-down-rpg-pixel-art">Top Down RPG Pixel Art</a></li><li><a href="/content/top-down-2d-rpg">Top-down 2D RPG</a></li><li><a href="/content/topdown-tiles">topdown tiles</a></li><li><a href="/content/trevas">Trevas</a></li><li><a href="/content/ultimate-tabletop">Ultimate TableTop</a></li><li><a href="/content/used-in-hero-of-allacrost">Used in Hero of Allacrost</a></li><li><a href="/content/used-in-valyria-tear">Used in Valyria tear</a></li><li><a href="/content/wastelander">Wastelander</a></li><li><a href="/content/workable-style-32x32-tiles">Workable style 32x32 tiles</a></li><li><a href="/content/zed-interesting-yet-unsorted">Zed - Interesting Yet Unsorted</a></li><li><a href="/content/zelda-like-rpg">Zelda Like RPG</a></li><li><a href="/content/zombie-buster-project">zombie-buster project</a></li></ul></div></div></div></div><div class="field field-name-favorites field-type-ds field-label-inline clearfix"><div class="field-label">Favorites:&nbsp;</div><div class="field-items"><div class="field-item even">235</div></div></div><div class="field field-name-flag-favorite field-type-ds field-label-hidden"><div class="field-items"><div class="field-item even"><span class="flag-wrapper flag-favorites flag-favorites-14914">
  679. // <a href="/flag/flag/favorites/14914?destination=node/14914&amp;token=NF4Z1O1g9CwLU2n65PscJkJeHBLLkg75lOKLirEfrdI" title="" class="flag flag-action flag-link-toggle" rel="nofollow">Add to Favorites</a><span class="flag-throbber">&nbsp;</span>
  680. }
  681. else {
  682. console.warn("The date is missing. There are no divs with a class " + submittedDateGrandParentClassName + " having a great grandchild");
  683. }
  684. info.titleHref = window.location.href;
  685. // console.log("info.title: " + info.title);
  686. // console.log("info.titleHref: " + info.titleHref);
  687. console.log("submittedDateStr: " + submittedDateStr);
  688. if (submittedDateStr !== null) {
  689. var createdParts = submittedDateStr.split(" ");
  690. if (createdParts.length >= 4) {
  691. // 0 is day of week spelled out
  692. var yI = 3;
  693. var dI = 2;
  694. var mI = 1;
  695. var tI = createdParts.length - 1;
  696. var yStr = createdParts[yI];
  697. var dStr = createdParts[dI];
  698. var mStr = createdParts[mI];
  699. if (dStr.endsWith(",")) {
  700. info.month = mStr;
  701. info.day = dStr.slice(0, -1);
  702. info.year = yStr;
  703. if (createdParts.length >= tI) {
  704. var tStr = createdParts[tI];
  705. if (tStr.includes(":")) {
  706. info.time = tStr;
  707. }
  708. else {
  709. console.warn("The time string wasn't found (doesn't have ':') as the last space-separated element of \""+submittedDateStr+"\"");
  710. }
  711. }
  712. }
  713. else {
  714. console.warn("A date in the format \"DAY_OF_WEEK MON, D, YYYY HH:MM\" was expected but got: \""+submittedDateStr+"\"");
  715. }
  716. }
  717. }
  718.  
  719. // var licenseAnchors = getAnchorsWhereClassStartsWith(licenseAnchorPrefix);
  720. var licenseContainerElements = document.getElementsByClassName(licenseAContainerClass);
  721. if (licenseContainerElements.length > 0) {
  722. info.licenses = [];
  723. }
  724. for (var lai=0, aMax=licenseContainerElements.length; lai < aMax; lai++) {
  725. var licenseAnchors = licenseContainerElements[lai].children;
  726. if (licenseAnchors.length > 0) {
  727.  
  728. console.log("Checking " + licenseAnchors.length + " license anchors...");
  729.  
  730. var licenseA = licenseAnchors[0];
  731. licenseA.exactLicenseVersion = null;
  732. if (verbose) {
  733. console.log(" checking " + licenseA.className + "...");
  734. // NOTE: .getAttribute("href") gets the raw value, but .href gets the resulting full URL.
  735. console.log(" licenseA.href is a " + typeof licenseA.href);
  736. console.log(" licenseA.href.toString is a " + typeof licenseA.href.toString);
  737. console.log(" licenseA.href.toString().includes is a " + typeof licenseA.href.toString().includes);
  738. }
  739. if (licenseA.href === undefined) {
  740. console.warn("A license a.href is undefined.");
  741. }
  742. // else if (typeof licenseA.href.toString !== 'function') {
  743. // console.warn("A license a.href.toString is not a function.");
  744. // }
  745. else if (typeof licenseA.href.includes !== 'function') {
  746. // NOTE: Firefox 48 removes the "contains" prototype--you must use includes!
  747. // console.warn("A license a.getAttribute(\"href\").includes is not a function.");
  748. console.warn("A license a.href.toString.includes is not a function.");
  749. }
  750. else {
  751. if (licenseA.href.includes("opengameart.org") || licenseA.href.startsWith("/")) {
  752. console.warn("The license anchor should be an external link to the license but is \"" + licenseA.href + "\"");
  753. }
  754. if (verbose) {
  755. console.log("licenseA.href: '''", );
  756. console.log(licenseA.href);
  757. console.log("'''");
  758. }
  759. if (licenseA.href.slice(-3, -2) == ".") {
  760. licenseA.exactLicenseVersion = licenseA.href.slice(-4, -1);
  761. }
  762. else {
  763. console.warn("slice at -3 is not '.' but '" + licenseA.href.slice(-3, -2) + "'. The license version seems to be malformed: \"" + licenseA.href + "\"");
  764. }
  765. info.licenses.push(licenseA);
  766. }
  767.  
  768. }
  769. else {
  770. console.warn("There is no anchor in a class like "+licenseAContainerClass+"*" + "[" + lai + "]");
  771. }
  772. }
  773. var attributionAncestorClassName = "field-name-field-copyright-notice";
  774. // ^ Can also be field-name-field-art-attribution (content: "Attribution Instructions")
  775. var attributionAncestorElements = document.getElementsByClassName(attributionAncestorClassName);
  776. if (attributionAncestorElements.length < 1) {
  777. // The field is optional, so only warn if verbose.
  778. if (verbose) {
  779. console.log("INFO: class \"" + attributionAncestorClassName + "\" is not present (This is an optional field).");
  780. }
  781. attributionAncestorClassName = "field-name-field-art-attribution";
  782. attributionAncestorElements = document.getElementsByClassName(attributionAncestorClassName);
  783. if (attributionAncestorElements.length < 1) {
  784. if (verbose) {
  785. console.log("INFO: class \"" + attributionAncestorClassName + "\" is not present (This is an optional field).");
  786. }
  787. return info;
  788. }
  789. else {
  790. info.goodAttributionNoticeFlag = "Attribution Instructions"
  791. }
  792. }
  793. else {
  794. info.goodAttributionNoticeFlag = "Copyright/Attribution Notice";
  795. }
  796.  
  797. if (!attributionAncestorElements[0].children[0].textContent.includes(info.goodAttributionNoticeFlag)) {
  798. console.warn("The " + attributionAncestorClassName + ".firstChild should contain \"" + info.goodAttributionNoticeFlag + "\" but is \"" + attributionAncestorElements[0].children[0].textContent + "\"")
  799. }
  800. var attributionE = attributionAncestorElements[0].children[1].firstChild;
  801. // ^ Such as <div class="field field-name-field-copyright-notice field-type-text-long field-label-above"> <!--attributionAncestorElements[0]-->
  802. // <div class="field-label">Copyright/Attribution Notice:&nbsp;</div> <!--attributionAncestorElements[0].children[0]-->
  803. // <div class="field-items"> <!--attributionAncestorElements[0].children[1]-->
  804. // <div class="field-item even">&quot;Adobe Town Set&quot;
  805. // Artist: bluecarrot16
  806. info.attributionNotice = attributionE.textContent;
  807. return info;
  808. }
  809.  
  810. function addButton() {
  811. 'use strict';
  812. var pageInfoE = getButtonContainer();
  813. if (pageInfoE == null) {
  814. console.log('The '+madeSpanClassName+' class was not found so the button wasn\'t added!');
  815. return;
  816. }
  817.  
  818. //or:
  819. // See https://www.w3schools.com/jsref/met_document_createelement.asp
  820. var btn = document.createElement("BUTTON"); // Create a <button> element
  821. btn.setAttribute("class", "button button-secondary");
  822. btn.setAttribute("style", "background-color: rgb(50%, 50%, 50%)");
  823. var btnText = "Copy Markdown";
  824. btn.innerHTML = btnText; // Insert text
  825. // Any URL starting with a slash comes after: "https://creativecommons.org/licenses"
  826. // otherwise it comes after "https://"
  827. // - A list of CC licenses is at <https://creativecommons.org/about/cclicenses/>.
  828.  
  829. btn.addEventListener("click", function(){
  830. btn.innerHTML = btnText;
  831. var info = getInfo();
  832. for (var i=0, max=info.licenses.length; i < max; i++) {
  833. populateCorrespondingLicenseFields(info.licenses[i]);
  834. }
  835. var markdownStr = getMarkdown(info);
  836. setClipboardText(markdownStr, btn);
  837. }); // end addEventListener click
  838. pageInfoE.appendChild(btn); // Append <button> for Markdown to whatever element was selected.
  839. }//end addButton
  840. function checkIfComplete() {
  841. // console.log("Monitoring page loading...");
  842. var ready = true;
  843. if (!hasAllClasses(doneClasses)) {
  844. ready = false;
  845. }
  846. if (ready) {
  847. if (verbose) {
  848. console.log("The page has loaded.");
  849. }
  850. clearInterval(checkTimer);
  851. addButton();
  852. console.log("The license detection will resume after a user clicks the copy license button.");
  853. }
  854. else {
  855. console.log("The document is not ready (or is missing required fields)...");
  856. }
  857. }
  858. checkTimer = setInterval(checkIfComplete, 200);
  859. })();