Greasemonkey: Re-write all links based on param - greasemonkey

I need alittle help with getting a script that will take param from the orginal link and re-write them into a new link. I guess it should be pretty easy but I'm a noob still when it comes to this.
Here is the orginal HTML code for 1 link. (should be replaced globaly on the page. image1.jpg, image2.jpg etc.)
<div align="center"><img src="/preview/image1.jpg" width="128" height="128" border="0" style="border: 0px black solid;" /></div>
This should be done global on all the links that contain the imagepath "/preview/"
Thanks to Brock Adams I kinda understand how to get the param values with this code but I still don't really get it how to re-write all the links in a page.
var searchableStr = document.URL + '&';
var value1 = searchableStr.match (/[\?\&]id=([^\&\#]+)[\&\#]/i) [1];
var value2 = searchableStr.match (/[\?\&]connect=([^\&\#]+)[\&\#]/i) [1];
and then rewrite the links with "newlink"
var domain = searchableStr.match (/\/\/([w\.]*[^\/]+)/i) [1];
var newlink = '//' + domain + '/' + value1 + '/data/' + value2 + '.ext';
If someone could be so nice to help me setup an example greasemonkey script I would be very greatful for it.

OK, This is a fairly common task and I don't see any previous, Stack Overflow questions like it -- at least in a 2 minute search.
So, here's a script that should do what you want, based on the information provided...
// ==UserScript==
// #name Site_X, image relinker.
// #namespace StackOverflow
// #description Rewrites the preview links to ???
// #include http://Site_X.com/*
// #include http://www.Site_X.com/*
// #include https://Site_X.com/*
// #include https://www.Site_X.com/*
// ==/UserScript==
function LocalMain () {
/*--- Get all the images that have /preview/ in their path.
*/
var aPreviewImages = document.evaluate (
"//img[contains (#src, '/preview/')]",
document,
null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
null
);
var iNumImages = aPreviewImages.snapshotLength;
GM_log (iNumImages + ' preview images found.');
/*--- Rewrite the parent links to our new specifications.
Note, all the target links are of the form:
<a href="/index.php?Submit=ok&seson=b1e4&connect=127.0.0.1&id=13033&name=on">
<img src="/preview/image1.jpg" width="128" height="128" border="0" style="border: 0px black solid;" />
</a>
The desired rewrite changes the link to this form:
<a href="{current page's domain}/{id-value}/data/{connect-value}.ext">
*/
for (var iLinkIdx=0; iLinkIdx < iNumImages; iLinkIdx++) {
var zThisImage = aPreviewImages.snapshotItem (iLinkIdx);
var zParentLink = zThisImage.parentNode;
//--- Get the key href parameters.
var sIdValue = sGetUrlParamValue (zParentLink, 'id');
if (!sIdValue) continue; //-- Oopsie, this link was a malformed.
var sConnectValue = sGetUrlParamValue (zParentLink, 'connect');
if (!sConnectValue) continue;
//--- Get the current page's domain. (Or just use a relative link.)
var sPageDomain = document.URL.match (/\/\/([w\.]*[^\/]+)/i) [1];
//--- Generate the desired link value.
var sDesiredLink = 'http://' + sPageDomain + '/' + sIdValue + '/data/' + sConnectValue + '.ext';
//--- Rewrite the target link.
zParentLink.href = sDesiredLink;
}
}
function sGetUrlParamValue (zTargLink, sParamName) {
var zRegEx = eval ('/[\?\&]' + sParamName + '=([^\&\#]+)[\&\#]/i');
var aMatch = (zTargLink.href + '&').match (zRegEx);
if (aMatch)
return decodeURI (aMatch[1]);
else
return null;
}
window.addEventListener ("load", LocalMain, false);

Related

How to get char code of fontawesome icon?

I'd like to use fontawesome icons in SVG scope. I cannot achieve it in common way, but I can add <text> element containing corresponding UTF-8 char and with font set to fontawesome, like that:
<text style="font-family: FontAwesome;">\uf0ac</text>
To make it clear I wrote a switch for getting useful icons:
getFontAwesomeIcon(name) {
switch (name) {
case 'fa-globe':
return '\uf0ac'
case 'fa-lock':
return '\uf023'
case 'fa-users':
return '\uf0c0'
case 'fa-ellipsis-h':
return '\uf141'
default:
throw '# Wrong fontawesome icon name.'
}
}
But of course that's ugly, because I must write it myself im my code. How can I get these values just from fontawesome library?
You can avoid producing such a list and extract the information from the font-awesome stylesheet on the fly. Include the stylesheet and set the classes like usual, i. e.
<tspan class="fa fa-globe"></tspan>
and you can do the following:
var icons = document.querySelectorAll(".fa");
var stylesheet = Array.from(document.styleSheets).find(function (s) {
return s.href.endsWith("font-awesome.css");
});
var rules = Array.from(stylesheet.cssRules);
icons.forEach(function (icon) {
// extract the class name for the icon
var name = Array.from(icon.classList).find(function (c) {
return c.startsWith('fa-');
});
// get the ::before styles for that class
var style = rules.find(function (r) {
return r.selectorText && r.selectorText.endsWith(name + "::before");
}).style;
// insert the content into the element
// style.content returns '"\uf0ac"'
icon.textContent = style.content.substr(1,1);
});
My two answers for two approaches to the problem (both developed thanks to ccprog):
1. Setting char by class definition:
In that approach we can define element that way:
<text class="fa fa-globe"></text>
And next run that code:
var icons = document.querySelectorAll("text.fa");
// I want to modify only icons in SVG text elements
var stylesheets = Array.from(document.styleSheets);
// In my project FontAwesome styles are compiled with other file,
// so I search for rules in all CSS files
// Getting rules from stylesheets is slightly more complicated:
var rules = stylesheets.map(function(ss) {
return ss && ss.cssRules ? Array.from(ss.cssRules) : [];
})
rules = [].concat.apply([], rules);
// Rest the same:
icons.forEach(function (icon) {
var name = Array.from(icon.classList).find(function (c) {
return c.startsWith('fa-');
});
var style = rules.find(function (r) {
return r.selectorText && r.selectorText.endsWith(name + "::before");
}).style;
icon.textContent = style.content.substr(1,1);
});
But I had some problems with that approach, so I developed the second one.
2. Getting char with function:
const getFontAwesomeIconChar = (name) => {
var stylesheets = Array.from(document.styleSheets);
var rules = stylesheets.map(function(ss) {
return ss && ss.cssRules ? Array.from(ss.cssRules) : [];
})
rules = [].concat.apply([], rules);
var style = rules.find(function (r) {
return r.selectorText && r.selectorText.endsWith(name + "::before");
}).style;
return style.content.substr(1,1);
}
Having that funcion defined we can do something like this (example with React syntax):
<text>{getFontAwesomeIconChar('fa-globe')}</text>

Expand/Collapse Works for First Two Web Parts Only

I am trying to Maximize/Minimize a Document list Web Part.
I used the following code from http://blog.pathtosharepoint.com/2008/10/25/expandcollapse-buttons-for-your-web-parts/
and it works for my first two Web Parts but not my other two. All I did was include their titles within my coding as a change. Therefore, there shouldn't be any issue with the display.
Any suggestions on what can cause this?
The only changes I made after the first 2 were working was I added 2 more title1 to include the other 2 Web Parts.
As you can see, the bottom 2 don't fully minimize on page load
fYI: inside the coding.. the titles are changed to "... Orders" but the ... is in place of the actual name
<script type="text/javascript">
// Expand/Collapse Buttons
function WPToggle(thisId, ImageId)
{
if (document.getElementById(thisId).style.display=="none")
{
document.getElementById(thisId).style.display="";
document.getElementById(ImageId).src = "/_layouts/images/minus.gif";
}
else
{
document.getElementById(thisId).style.display="none";
document.getElementById(ImageId).src = "/_layouts/images/plus.gif";
}
}
function ExpandCollapseBody()
{
var i = 1;
var WPid = "WebPartWPQ1" ;
var WPtitleid = "WebPartTitleWPQ1" ;
var Toggleid = "ToggleImage1" ;
do
{
try
{
title1 = document.getElementById(WPtitleid).getAttribute("title");
if (title1 == "... Orders" || title1 == "... Orders" || title1 =="... Orders" || title1 == "... Orders")
{
document.getElementById(WPtitleid).innerHTML = '<IMG id="' + Toggleid + '" onClick="WPToggle(\'' + WPid + '\',\'' + Toggleid +
'\')" alt="Expand/Collapse" style="margin:6px 5px 0px 2px; float:left; cursor:pointer;" src="/_layouts/images/minus.gif" />' +
document.getElementById(WPtitleid).innerHTML ;
document.getElementById(Toggleid).src = "/_layouts/images/plus.gif";
}
}
catch(err) {}
i = i + 1;
WPid = "WebPartWPQ" + i ;
WPtitleid = "WebPartTitleWPQ" + i;
Toggleid = "ToggleImage" + i;
} while (document.getElementById(WPid))
}
_spBodyOnLoadFunctionNames.push("ExpandCollapseBody()");
</script>
I guess I see that by default, the more I add more webparts they start at expanded rather than collapse....
I see. I need the following condition of Chrome: minimize for the Web Part

html2canvas does not print jsPlumb Connectors

How to print SVG elements that are built by jsPlumb.
Known that getting all SVG Elements drawen by jsPlumb is retrieved by this code :
var uiJsPlumbConnectors=jsPlumb.getAllConnections().map(function(conn){return conn.canvas;})
All connectors are SVG elements :
Using html2canvas to print all connectors (SVG), it does not work :
html2canvas(uiJsPlumbConnectors).then(function(c){
window.open(c.toDataURL('image/png'))
});
An image has been generated , however, it is an emply image .
FIDDLE
It seems that html2canvas does not support yet multi-elements drawing ?
Last time I checked html2canvas was not able to convert SVGs, you will need another script to handle that.
The steps:
transfer html elements to canvas
transfer svg elements to canvas
export canvas
I used https://code.google.com/p/canvg/ to export to the same canvas after using html2canvas. Hope that helps you.
I just implemented this
<%--stuff for printing--%>
<script type="text/javascript" src="../../../../Scripts/Print/html2canvas.js"></script>
<script src="<%=AdminPath%>Scripts/canvg/rgbcolor.js" type="text/javascript"></script>
<script src="<%=AdminPath%>Scripts/canvg/StackBlur.js" type="text/javascript"></script>
<script src="<%=AdminPath%>Scripts/canvg/canvg.js" type="text/javascript"></script>
jsplumb div
<div class="demo statemachine-demo" id="statemachine-demo" style="margin: 0px;">
</div>
hidden div for printing
<div id="canvasDiv" style='visibility:hidden;' >
</div>
function renderImage()
{
var statemachinediv = document.getElementById('statemachine-demo');
html2canvas([statemachinediv], {
onrendered: function (canvas) {
document.getElementById('canvasDiv').appendChild(canvas);
var svgList = $(statemachinediv).find( "svg" );
svgList.each(function(index, value) {
try
{
var svgExample = this;
var serializer = new XMLSerializer();
var svgMarkup = serializer.serializeToString(svgExample);
if(svgMarkup.indexOf("_jsPlumb_connector") > -1)
{
var leftIndex = svgMarkup.indexOf("left: ");
var endOfLeft = svgMarkup.indexOf("px", leftIndex);
var leftPosition = svgMarkup.substring(leftIndex+6, endOfLeft );
var left = parseInt(leftPosition);
var topIndex = svgMarkup.indexOf("top: ");
var endOfTop = svgMarkup.indexOf("px", topIndex);
var topPosition = svgMarkup.substring(topIndex+5, endOfTop );
var top = parseInt(topPosition);
svgMarkup = svgMarkup.replace('xmlns="http://www.w3.org/2000/svg"','');
var connectorCanvas = document.createElement('canvas');
canvg(connectorCanvas, svgMarkup); //add connector to canvas
var context = canvas.getContext('2d');
context.drawImage(connectorCanvas, left, top);
}
}
catch(err)
{
showBalloon('error in print');
}
});
var stateMachineName = $("#stateMachineDropDown option:selected").text();
var data = canvas.toDataURL('image/png');
var mywindow = window.open('', 'my div', 'height=400,width=600');
mywindow.document.write('<html><head><title>' + stateMachineName + '</title>');
mywindow.document.write('</head><body ><table><tr><td>');
mywindow.document.write('</td></tr></table><img src="' + data + '" />');
mywindow.document.write('</body></html>');
mywindow.print();
}
});
return false;
}
Its a old question, but, this helped me. Mode details.
$clone.find('.jtk-connector').each(function () {
// for every SVG element created by JsPlumb for connections...
var left = parseInt(this.style.left, 10) + 'px';
var top = parseInt(this.style.top, 10) + 'px';
this.removeAttribute('style');
this.removeAttribute('position');
this.setAttribute('width', parseInt(this.getAttribute('width'), 10) + 'px');
this.setAttribute('height', parseInt(this.getAttribute('height'), 10) + 'px');
this.setAttribute('preserveAspectRatio', 'xMidYMid meet');
this.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
// this.children[0] is the path for connection line
// this.children[1] is the path for connection arrow shape
this.children[0].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
this.children[1].setAttribute('xmlns', 'http://www.w3.org/2000/svg');
this.setAttribute('viewbox', '0 0 ' + parseInt(this.getAttribute('width'), 10) + ' ' + parseInt(this.getAttribute('height'), 10));
this.children[0].setAttribute('stroke-width', '2px');
this.children[0].setAttribute('stroke', '#c9c9c9');
this.children[1].setAttribute('fill', '#c9c9c9');
this.children[1].setAttribute('stroke', '#c9c9c9');
$clone.find(this).wrap('<span style="position: absolute; left: ' + left + '; top: ' + top + ';"></span>');
});

Meteor Facebook Profile Picture not Displaying

On first sign I have the following code:
Accounts.onCreateUser(function(options,user){
if (typeof(user.services.facebook) != "undefined") {
user.services.facebook.picture = "http://graph.facebook.com/" + user.services.facebook.id + "/picture/?type=large";
}
return user;
});
Which results in the following URL string
http://graph.facebook.com/[myfacebookid]/picture/?type=large
Yet when it renders that url and returns
<img scr="http://graph.facebook.com/[myfacebookid]/picture/?type=large" alt="My Name">
All I see is a broken image. How can I pull this in so that it renders the facebook profile picture?
I use a helper function based off of the Facebook ID of the user to grab the image on the server. I notice my url has /picture? and your has /picture/? Hope this helps.
userPicHelper: function() {
if (this.profile) {
var id = this.profile.facebookId;
var img = 'http://graph.facebook.com/' + id + '/picture?type=square&height=160&width=160';
return img;
}
},
I don't know how I missed this before, but is this the src attribute on the image tag is actually written as scr:
<img scr=
Should be...
<img src=
You have http instead of https.
So:
"https://graph.facebook.com/" + id + "/picture/?type=large";
This was my problem.

Opencart 1.5.4 Search by Description

I have read various entries about searching by description and subcategories in opencart by default but I have a unique problem. I have two header files because my site has 2 headers... one for the home page and one for every other page.
Home Page:
https://garrysun.com/
Other Page:
https://garrysun.com/ayurveda-products/categories
When I search on the home page I get the correct results (search the word "heart") but when I search any other page it doesn't return the search for descriptions or subcategories.
Home Page Search Results:https://garrysun.com/index.php?route=product/search&filter_description=true&filter_sub_category=true&filter_name=heart
Other Page Search Results:https://garrysun.com/index.php?route=product/search&filter_name=heart
As you can see, when I search the other page the extra code is not being added to search in descriptions and subcategories.
So why is this new code that I added working for the home page an not any other page?
To make this search function work I have changed the common.js file to look like this (adding the two lines below each "url= $(base..." section:
/* Search */
$('.button-search').bind('click', function() {
url = $('base').attr('href') + 'index.php?route=product/search';
url += '&filter_description=true'; // ADDED this to search descriptions
url += '&filter_sub_category=true'; // ADDED this to search sub-categories
var filter_name = $('input[name=\'filter_name\']').attr('value');
if (filter_name) {
url += '&filter_name=' + encodeURIComponent(filter_name) ;
}
location = url;
});
$('#header input[name=\'filter_name\']').bind('keydown', function(e) {
if (e.keyCode == 13) {
url = $('base').attr('href') + 'index.php?route=product/search';
url += '&filter_description=true'; // ADDED this to search descriptions
url += '&filter_sub_category=true'; // ADDED this to search sub-categories
var filter_name = $('input[name=\'filter_name\']').attr('value');
if (filter_name) {
url += '&filter_name=' + encodeURIComponent(filter_name) ;
}
location = url;
}
});
Both header files use the same code to call the search function:
<div id="search">
<div class="button-search"></div>
<?php if ($filter_name) { ?>
<input type="text" name="filter_name" value="<?php echo $filter_name; ?>" />
<?php } else { ?>
<input type="text" name="filter_name" value="<?php echo $text_search; ?>" onclick="this.value = '';" onkeydown="this.style.color = '#000000';" />
<?php } ?>
</div>
</div>
After trying to figure out what's wrong in your code for few minutes (unsuccessfully), I ran a network debugging and found out that nothing is wrong with your code, you are just calling 2 different Javascript files(!):
On your home page, you are using common.js that is located at https://garrysun.com/catalog/view/javascript/common.js.
On your category pages, you are using common.js that is located at https://garrysun.com/catalog/view/javascript/add2cart-go2cart/common.js.
The 2nd one does not include your modifications, and looks like this:
$('.button-search').bind('click', function() {
url = $('base').attr('href') + 'index.php?route=product/search';
var filter_name = $('input[name=\'filter_name\']').attr('value');
if (filter_name) {
url += '&filter_name=' + encodeURIComponent(filter_name);
}
location = url;
});
$('#header input[name=\'filter_name\']').bind('keydown', function(e) {
if (e.keyCode == 13) {
url = $('base').attr('href') + 'index.php?route=product/search';
var filter_name = $('input[name=\'filter_name\']').attr('value');
if (filter_name) {
url += '&filter_name=' + encodeURIComponent(filter_name);
}
location = url;
}
});
Vuala.
Hope this helps!

Resources