Changing URL strings via JS on MediaWiki site - javascript

So...I've been setting up a brand-new wiki for the past four days. While everything's going almost smoothly, I'd like to deal with a special touchup.
I created a preload template à la Wikipedia, "Template starter", some hours ago. While I could go the other way and create an input form, I want to make it so that red links in the Template namespace always lead to the code from this page, whenever a new one is ready for creation. So that:
http://rfm.referata.com/w/index.php?title=Template:Foo&action=edit&redlink=1 (default)
becomes:
http://rfm.referata.com/w/index.php?title=Template:Foo&action=edit&redlink=1&preload=Template:Template+starter (target)
by way of a JavaScript snippet added to the site's Common.js and Mobile.js.
Haven't come across similar MW-based examples, so I'd like to make sure everything's A-O.K.

Working from this answer, you could do something like this in Mediawiki:Common.js:
$(function() {
var preload = 'Template:Template_starter';
$("body.ns-10 #mw-content-text a.new").attr('href', function(i, h) {
// Maybe some links already have a preload parameter.
if (h.indexOf('preload=') !== -1) {
return h;
}
// All others get it appended.
return h + "&preload=" + preload;
});
});
Note that the check for a pre-existing '&preload=' isn't all that robust.

This extension should work well in your case https://www.mediawiki.org/wiki/Extension:NewArticleTemplate

Improving on what you provided last time, Mr. Wilson:
$(function() {
var preload = 'Template:Template_starter';
$("a.new[href*='Template:']").attr('href', function(i, h) {
// Maybe some links already have a preload parameter.
if (h.indexOf('preload=') !== -1) {
return h;
}
// All others get it appended.
return h + "&preload=" + preload;
});
});
Note that the previous version only worked within pages in the Template namespace; this fix applies to all pages with a red link to a nonexistent template. Thanks a dozen!

Related

Casper/Phantomjs unable to retrieve highest resolution src image

I am trying to make a basic Instagram web scraper, both art inspiration pictures and just generally trying to boost my knowledge and experience programming.
Currently the issue that I am having is that Casper/Phantomjs can't detect higher res images from the srcset, and I can't figure out a way around this. Instagram has their srcsets provide 640x640, 750x750, and 1080x1080 images. I would obviously like to retrieve the 1080, but it seems to be undetectable by any method I've tried so far. Setting the viewport larger does nothing, and I can't retrieve the entire source set through just getting the HTML and splitting it where I need it. And as far as I can tell, there is no other way to retrieve said image than to get it from this srcset.
Edit
As I was asked for more details, here I go. This is the code I used to get the attributes from the page:
function getImages() {
var scripts = document.querySelectorAll('._2di5p');
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute('src');
});
}
Then I do the standard:
casper.waitForSelector('div._4rbun', function() {
this.echo('...found selector ...try getting image srcs now...');
imagesArray = this.evaluate(getImages);
imagesArray.forEach(function (item) {
console.log(item);
However, all that is returned is the lowest resolution of the srcset. Using this url, for example, (https://www.instagram.com/p/BhWS4csAIPS/?taken-by=kasabianofficial) all that is returned is https://instagram.flcy1-1.fna.fbcdn.net/vp/b282bb23f82318697f0b9b85279ab32e/5B5CE6F2/t51.2885-15/s640x640/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg, which is the lowest resolution (640x640) image in the srcset. Ideally, I'd like to retrieve the https://instagram.flcy1-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg which is the 1080x1080 image in the srcset. But I can't. There's no way to get that item as far as I can tell. It's completely hidden.
I found a way around it in Instagram's case. Instagram puts the source picture in a meta tag within the head. So, using the code I'll paste below, you can call all of the meta tags and then sort out which one is the source picture by checking if "og:image" is retrieved.
function getImages() {
var scripts = document.querySelectorAll('meta[content]');
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute('property') + " " + e.getAttribute('content');
});
}
And this is the way to sort the meta tags into only having the original image in its native resolution.
this.echo('...found selector ...try getting image srcs now...');
imagesArray = this.evaluate(getImages);
imagesArray.forEach(function (item) {
if (typeof item == "string" && item.indexOf('og:image') > -1) {
Edit: Unfortunately this only works for single image posts on Instagram (the site I'm trying to scrape) so this unfortunately does me no goo. The values within the meta tags don't change even if you load the next image in the post. I'm leaving this up though in case anyone else could use it, but it's not ideal for my own use case.
Yes indeed PhantomJS doesn't seem to support srcset, its Webkit engine is very old.
But to be fair, all the metadata related to the page is out in the open in the HTML as JSON in window._sharedData variable.
If you want to use a headless browser (and not parse it with any server-side language) you can do this:
var imgUrl = page.evaluate(function(){
return window._sharedData.entry_data.PostPage[0].graphql.shortcode_media.display_resources[2].src;
});
https://instagram.fhen2-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg
Solution: So my solution was to use slimerjs. If I run the js file through "casperjs --engine=slimerjs fileName.js", I can retrieve srcsets in full. So if I say use this code:
function getImgSrc() {
var scripts = document.querySelectorAll("._2di5p");
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute("srcset");
});
}
on this url (https://www.instagram.com/p/BhWS4csAIPS/?taken-by=kasabianofficial) I will get (https://instagram.flcy1-1.fna.fbcdn.net/vp/b282bb23f82318697f0b9b85279ab32e/5B5CE6F2/t51.2885-15/s640x640/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg 640w,https://instagram.flcy1-1.fna.fbcdn.net/vp/b4eebf94247af02c63d20320f6535ab4/5B6258DF/t51.2885-15/s750x750/sh0.08/e35/29740443_908390472665088_4690461645690896384_n.jpg 750w,https://instagram.flcy1-1.fna.fbcdn.net/vp/8d20f803e1cb06e394ac91383fd9a462/5B5C9093/t51.2885-15/e35/29740443_908390472665088_4690461645690896384_n.jpg 1080w) as the result.
This is what I wanted as it means I can scrape those 1080 images. Sorry for this messy page, but I wanted to leave my trail of steps to any of those who might be trying like me.

SessionStorage Navigation

Greets, so I I'm trying to learn jquery/javascript storage and ran into an issue where I am building a navigation that should remember and place you where you last were if you refresh the page (that's why i use sessionStorage rather then localStorage).
But I can't seem to change the sessionStorage variable to the new location, nor figure out a functional way to get the user back on refreshing the page.
This is what I currently have.
$(function() {
sessionStorage.setItem('position', '.first');
var location = sessionStorage.getItem('position');
$('li', this).click(function() {
cls = $(this).text();
if('.' + cls != location) {
$(location).slideToggle(400);
$('.' + cls).delay(400).slideToggle(400);
sessionStorage.setItem('position', '.' + cls)
console.log(location)
};
});
});
https://jsfiddle.net/Unkn0wn96/ndj9sqpe/
The code works in an very odd way, rather then how it's intended, including never changing the value when I console.log(location).
I made some further testing on this and found a 'more' working way in the was that the sessionStorage does change to something, yet it not being usefull.
https://jsfiddle.net/Unkn0wn96/nkbtykkr/
but yet, they elements don't toggle as they should, including that when I console log sessionStorage.position it returns NaN. Also for some odd reason I can't store sessionStorage.position within a variable, it just refuses to change its value. I have no clue why this is happening.
So I was finally able to solve my issue with sessionStorage, since there was not much of help I'd assume the information regarding the case was limited and so wish to share my solution. All thought it does not work fully as intended it does execute it's main function.
$(function() {
$('button').on('click', function() {
var msg = '.'+$(this).text();
localStorage.setItem('color', 'blue') //Default (does not matter since the if statement does not register)
if(msg != '.' + localStorage.color) { // DOES NOT REGISTER
if(localStorage.length > 0) {
localStorage.removeItem('color')
console.log('localStorage.length : ' + localStorage.length)
};
localStorage.setItem('color', msg)
console.log(localStorage.color)
} else {
console.log('cancelled')
}
});
});
https://jsfiddle.net/mdqjoz69/4/
So what I finally was able to achieve was to make a localStorage key change it's value regarding of what button you press.
What I failed to achieve was being able to check the stored data to not execute whenever you store something that have already been stored. There might be a work around for this. But since the code serves its main purpose I'll let it slide.

My JSLink script will not work

I am attempting to use JSLink ..finally.. and I am having some trouble that I cannot seem to straighten out. For my first venture down the rabbit hole I chose something super simple for use as proof of concept. So I looked up a tutorial and came up with a simple script to draw a box around the Title field of each entry and style the text. I cannot get this to work. Is there any chance you can take a look at this code for me? I used the following tokens in the JSLink box.
~sitecollection/site/folder/folder/file.js
And
~site/folder/folder/file.js
The .js file is stored on the same site as the List View WebPart I am attempting to modify. The list only has the default “Title” column.
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
It looks as though you are attempting to override the context (ctx) item itself, where you actually just want to override the list field and the list view in which the field is displayed. Make sense?
Firstly, change overrideContext.Templates.Item to overrideContext.Templates.Fields :
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields = {
// Add field and point it to your rendering function
"Title": { "View": overrideTemplate },
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
Then when the JSLink runs the renderer looks for the Title field in the List view, and applies your overrideTemplate function.
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
In terms of running multiple JSLinks on a SharePoint page, it is quite possible to run multiple JSLink scripts, they just need to be separated by the pipe '|' symbol. I use SharePoint Online a lot and I see the following formatting working all the time (sorry Sascha!).
~site/yourassetfolder/yourfilename.js | ~site/yourassetfolder/anotherfilename.js
You can run as many scripts concurrently as you want, just keep separating them with the pipe. I've seen this on prem also, however you might want to swap out '~sites' for '~sitecollection' and make sure the js files you are accessing are at the top level site in the site collection if you do so!
I have noticed when running multiple JSLinks on a list or page because they are all doing Client Side Rendering, too many will slow your page down. If this happens, you might want to consider combining them into one JSLink script so that the server only has to call one file to return to the client to do all the rendering needed for your list.
Hope this helps.

How to trigger a JavaScript function using the URL

I really didn't know how to explain my question in the title, so I tried.
Anyways, this is my problem. I have a webpage which is basically a puzzle. The basic premise of it is that when you visit a certain link, it will trigger a function and show the next piece.
Here's one of the functions that will show the piece -
function showone() {
var elem = document.getElementById("one");
if (elem.className = "hide") {
elem.className = "show"
}
}
The reason that it's built like this, is because the pieces are constructed and placed using an HTML table, using classes to hide and show them.
What I need to do, is somehow create a URL that will trigger a new piece. For example, "www.website.com/index.html?showone" is what I'd like. This would trigger the "showone" function.
I don't know how to do this though, and after a fair bit of searching, I'm more confused than I was to begin with.
The reason I'm using JavaScript to begin with, is that the page can't refresh. I understand that this might not be possible, in which case, I'm open to any suggestions on how I could get this to work.
Thanks in advance, any suggestions would be greatly appreciated.
-Mitchyl
Javascript web application frameworks can to this for you, they allow to build web application without refresh page.
For example you can use backbonejs it has Router class inside and it very easy to use.
code is easy as :
var Workspace = Backbone.Router.extend({
routes: {
"help": "help", // #help
"search/:query": "search", // #search/kiwis
"search/:query/p:page": "search" // #search/kiwis/p7
},
help: function() {
...
},
search: function(query, page) {
...
}
});
is also you can use angularjs it is big one that supports by Google.
Maybe this solution can help you?
$("a.icon-loading-link").click(function(e){
var link = $(e.target).prop("href"); //save link of current <a> into variable
/* Creating new icon-tag, for example $("<img/>", {src: "link/to/file"}).appendTo("next/dt"); */
e.preventDefault(); //Cancel opening link
return false; //For WebKit browsers
});

onClick replace /segment/ of img src path with one of number of values

No idea what I'm doing or why it isn't working. Clearly not using the right method and probably won't use the right language to explain the problem..
Photogallery... Trying to have a single html page... it has links to images... buttons on the page 'aim to' modify the path to the images by finding the name currently in the path and replacing it with the name of the gallery corresponding to the button the user clicked on...
example:
GALLERY2go : function(e) {
if(GalleryID!="landscapes")
{
var find = ''+ findGalleryID()+'';
var repl = "landscapes";
var page = document.body.innerHTML;
while (page.indexOf(find) >= 0) {
var i = page.indexOf(find);
var j = find.length;
page = page.substr(0,i) + repl + page.substr(i+j);
document.body.innerHTML = page;
var GalleryID = "landscapes";
}
}
},
There's a function higher up the page to get var find to take the value of var GalleryID:
var GalleryID = "portfolio";
function findGalleryID() {
return GalleryID
}
Clearly the first varGalleryID is global (t'was there to set a default value should I have been able to find a way of referring to it onLoad) and the one inside the function is cleared at the end of the function (I've read that much). But I don't know what any of this means.
The code, given its frailties or otherwise ridiculousness, actually does change all of the image links (and absolutely everything else called "portfolio") in the html page - hence "portfolio" becomes "landscapes"... the path to the images changes and they all update... As a JavaScript beginner I was pretty chuffed to see it worked. But you can't click on another gallery button because it's stuck in a loop of some sort. In fact, after you click the button you can't click on anything else and all of the rest of the JavaScript functionality is buggered. Perhaps I've introduced some kind of loop it never exits. If you click on portfolio when you're in portfolio you crash the browser! Anyway I'm well aware that 'my cobbled together solution' is not how it would be done by someone with any experience in writing code. They'd probably use something else with a different name that takes another lifetime to learn. I don't think I can use getElement by and refer to the class/id name and parse the filename [using lots of words I don't at all understand] because of the implications on the other parts of the script. I've tried using a div wrapper and code to launch a child html doc and that come in without disposing of the existing content or talking to the stylesheet. I'm bloody lost and don't even know where to start looking next.
The point is... And here's a plea... If any of you do reply, I fear you will reply without the making the assumption that you're talking to someone who really hasn't got a clue what AJAX and JQuery and PHP are... I have searched forums; I don't understand them. Please bear that in mind.
I'll take a stab at updating your function a bit. I recognize that a critique of the code as it stands probably won't help you solve your problem.
var currentGallery = 'landscape';
function ChangeGallery(name) {
var imgs = document.getElementsByTagName("img") // get all the img tags on the page
for (var i = 0; i < imgs.length; i++) { // loop through them
if (imgs[i].src.indexOf(currentGallery) >= 0) { // if this img tag's src contains the current gallery
imgs[i].src = imgs[i].src.replace(currentGallery, name);
}
}
currentGallery = name;
}
As to why I've done what I've done - you're correct in that the scope of the variables - whether the whole page, or only the given function, knows about it, is mixed in your given code. However, another potential problem is that if you replace everything in the html that says 'landscape' with 'portfolio', it could potentially change non-images. This code only finds images, and then replaces the src only if it contains the given keyword.

Categories