Is there a way to make the nodes draggable/to another parent or child node to rearrange the nodes in d3.js - d3.js

While searching for hierarchical org chart controls, I came across a post on how to orient the nodes in d3.js, and I was wondering if there 1) was a way to edit the tree/drag children. 2) how to export the edited tree.

To answer your second question, one way is to grab the content of the parent node of your SVG (let's say your SVG is contained in a node with the id my_svg_container), and repackage it as a "true" SVG file that can be opened in an SVG-capable editor like Inkscape or Illustrator:
var rawSvg = $('#my_svg_container').outerHTML();
var result = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1">' + rawSvg + '</svg>';
The outerHTML() function:
jQuery.fn.outerHTML = function() {
return jQuery('<div />').append(this.eq(0).clone()).html();
};
Then use a hidden web form to POST that result to a CGI script that prints it to the requesting web browser as a file. The form is triggered when a button is clicked or some other event occurs that is set to trigger the form. The browser then queries the user to save the file to the local file system.
If an example form contains the fields svg_data and svg_fn, which contain the SVG result and some filename of your choice, a very basic Perl script might look something like:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Pretty qw/:standard/;
my $val = param('svg_data');
my $fn = param('svg_fn');
print "Content-Type: application/x-gzip\n";
print "Content-Disposition: attachment; filename=$fn\n";
print "Content-Description: File to download\n\n";
print $val;
You might add some data validation code to make sure you're printing an SVG file and not something else.

Related

Extract width and height from image links via ImgApp Google Sheet Library

I want to extract the dimensions of the image from the URL in google Sheet. Found this Library that does exactly what I am after.
https://github.com/tanaikech/ImgApp#getsize
But I am very new to this scenario and wondering what exactly I should use in the script editor. If I follow the above I can't get the results.
Please help.
Thanks
When I saw your provided sample Spreadsheet, it seems that the Spreadsheet and your script are as follows.
function myFunction() {
var blob = DriveApp.getFileById(fileId).getBlob();
var res = ImgApp.getSize(blob);
var width = res.width;
var height = res.height;
}
Modification points:
In this case, you put a custom function of =myFunction(A2) to a cell. But your script doesn't retrieve the value.
At the custom function, DriveApp.getFileById(fileId) cannot be used because of the limitation.
Your script doesn't return the values.
When these points are reflected in the script for achieving your goal, it becomes as follows.
Modified script:
Please replace your current script with the following script and save the script. And, please put a custom function of =myFunction(A2) to a cell. By this, the width and height are returned.
function myFunction(url) {
const blob = UrlFetchApp.fetch(url).getBlob();
const { width, height } = ImgApp.getSize(blob);
return [[width, height]];
}
Testing:
When this modified script is used for your sample Spreadsheet, it becomes as follows.
References:
Custom Functions in Google Sheets
ImgApp

kendo ui editor how to modify user selection with range object

Kendo UI 2015.2.805 Kendo UI Editor for Jacascript
I want to extend the kendo ui editor by adding a custom tool that will convert a user selected block that spans two or more paragraphs into block of single spaced text. This can be done by locating all interior p tags and converting them into br tags, taking care not to change the first or last tag.
My problem is working with the range object.
Getting the range is easy:
var range = editor.getRange();
The range object has a start and end container, and a start and end offset (within that container). I can access the text (without markup)
console.log(range.toString());
Oddly, other examples I have seen, including working examples, show that
console.log(range);
will dump the text, however that does not work in my project, I just get the word 'Range', which is the type of the object. This concerns me.
However, all I really need however is a start and end offset in the editor's markup (editor.value()) then I can locate and change the p's to br's.
I've read the telerik documentation and the referenced quirksmode site's explanation of html ranges, and while informative nothing shows how to locate the range withing the text (which seems pretty basic to me).
I suspect I'm overlooking something simple.
Given a range object how can I locate the start and end offset within the editor's content?
EDIT: After additional research it appears much more complex than I anticipated. It seems I must deal with the range and/or selection objects rather than directly with the editor content. Smarter minds than I came up with the range object for reasons I cannot fathom.
Here is what I have so far:
var range = letterEditor.editor.getRange();
var divSelection;
divSelection = range.cloneRange();
//cloning may be needless extra work...
//here manipulate the divSelection to how I want it.
//divSeletion is a range, not sure how to manipulate it
var sel = letterEditor.editor.getSelection()
sel.removeAllRanges();
sel.addRange(divSelection);
EDIT 2:
Based on Tim Down's Solution I came up with this simple test:
var html;
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
html = html.replace("</p><p>", "<br/>")
var range = letterEditor.editor.getRange();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = html;
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
range.insertNode(frag);
The first part, getting the html selection works fine, the second part also works however the editor inserts tags around all lines so the result is incorrect; extra lines including fragments of the selection.
The editor supports a view html popup which shows the editor content as html and it allows for editing the html. If I change the targeted p tags to br's I get the desired result. (The editor does support br as a default line feed vs p, but I want p's most of the time). That I can edit the html with the html viewer tool lets me know this is possible, I just need identify the selection start and end in the editor content, then a simple textual replacement via regex on the editor value would do the trick.
Edit 3:
Poking around kendo.all.max.js I discovered that pressing shift+enter creates a br instead of a p tag for the line feed. I was going to extend it to do just that as a workaround for the single-space tool. I would still like a solution to this if anyone knows, but for now I will instruct users to shift-enter for single spaced blocks of text.
This will accomplish it. Uses Tim Down's code to get html. RegEx could probably be made more efficient. 'Trick' is using split = false in insertHtml.
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
var block = container.innerHTML;
var rgx = new RegExp(/<br class="k-br">/gi);
block = block.replace(rgx, "");
rgx = new RegExp(/<\/p><p>/gi);
block = block.replace(rgx, "<br/>");
rgx = new RegExp(/<\/p>|<p>/gi);
block = block.replace(rgx, "");
letterEditor.editor.exec("insertHtml", { html: block, split: false });
}

PhantomJS - Rendering fails to show all images

I have a phantomjs script that is stepping through the pages of my site.
For each page, I use page = new WebPage() and then page.close() after finishing with the page. (This is a simplified description of the process, and I'm using PhantomJS version 1.9.7.)
While on each page, I use page.renderBase64('PNG') one or more times, and add the results to an array.
When I'm all done, I build a new page and cycle through the array of images, adding each to the page using <img src="data:image/png;base64,.......image.data.......">.
When done, I use page.render(...) to make a PDF file.
This is all working great... except that the images stop appearing in the PDF after about the 20th image - the rest just show as 4x4 pixel black dots
For troubleshooting this...
I've changed the render to output a PNG file, and have the same
problem after the 19th or 20th image.
I've outputted the raw HTML. I
can open that in Chrome, and all the images are visible.
Any ideas why the rendering would be failing?
Solved the issue. Turns out that PhantomJS was still preparing the images when the render was executed. Moving the render into the onLoadFinished handler, as illustrated below, solved the issue. Before, the page.render was being called immediately after the page.content = assignment.
For those interested in doing something similar, here's the gist of the process we are doing:
var htmlForAllPages = [];
then, as we load each page in PhantomJS:
var img = page.renderBase64('PNG');
...
htmlForAllPages.push('<img src="data:image/png;base64,' + img + '">');
...
When done, the final PDF is created... We have a template file ready, with all the required HTML and CSS etc. and simply insert our generated HTML into it:
var fs = require('fs');
var template = fs.read('DocumentationTemplate.html');
var finalHtml = template.replace('INSERTBODYHERE', htmlForAllPages.join('\n'));
var pdfPage = new WebPage();
pdfPage.onLoadFinished = function() {
pdfPage.render('Final.pdf');
pdfPage.close();
};
pdfPage.content = finalHtml;

jQuery UI Multiselect Widget With Images (Eric Hynds Version)

The excellent dropdown jQuery UI Multiselect widget that supports styling via jQuery UI Themeroller still doesn't have support for including images within the drop down rows.
I didn't see any answers to this problem within Stackoverflow yet it seems to be asked regularly in various areas of the internet, so I am giving the answer to this question below..
(ALSO See my FIDDLE Example to see this in action,)
The following is based on an initial idea by 'pdlove' for introducing the use of images within this excellent UI Multiselect for jQuery.
Adding Image support for line items in check box text area is achieved by setting out the selector option rows html like this:
<option value="somevalue" image="yourimage.jpg" class="multSelktrImg">
normal visible text
</option>
I would also add a class control to your style sheet css file to set the image size being rendered in the option line items of the drop down, along with a couple of position settings for the image, label and span text.
In this example I use the class name 'multSelktrImg', so within the css file it would look something like this:
.multSelktrImg span{position: relative;top: 10px;vertical-align: middle;
display: inline-flex;}
.multSelktrImg input {vertical-align: -2px;}
.multSelktrImg img {position: relative;height: 30px;margin: 2px 6px;top: -10px;}
Now for the change in the src/jquery.multiselect.js file
Search for the following matching code around line 130 (depending on what version id of the script you are using):
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
title = this.innerHTML,
description = this.title,
....
ADD the following line above "title = this.innerHTML,":
image = this.getAttribute("image");
so that it looks like this:
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
image = this.getAttribute("image");
title = this.innerHTML,
description = this.title,
Now Search for the following matching code around line 180:
// add the title and close everything off
html += ' /><span>' + title + '</span></label></li>';
....
Replace the code line with the following to allow for rendering of your images:
// add the title and close everything off
html += ' /><span>';
if (image != null) {
html += '<img src="'+image+'" class="multSelktrImg">';
}
html += title + '</span></label></li>';
save the new version of the script src/jquery.multiselect.js file and now the images will appear in the multiselect drop down. Use the 'multSelktrImg' class value to control the size of the image displayed by altering the pixel size for the class in your css file.
In the FIDDLE version, I have altered the minimized version of the jQuery script, and created an initialisation of the Select object.

bookmarklet to apply xslt stylesheet to a displayed xml file

How would I write a bookmarklet that applies a given XSLT stylesheet to XML file that is displayed in, e.g., firefox? The XML Document is already loaded in the browser and displayed without a stylesheet, and the XSLT is available under a fixed URL which should be encoded in the bookmarklet.
Here is an example:
A bookmarklet for applying an XSLT stylesheet to an XML document - just insert the base64 encoded xsl in atob("") - tested on firefox
javascript: (function() {
var parser = new DOMParser();
var ss = parser.parseFromString(atob(""), 'application/xml');
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(ss);
var newdoc = xsltProcessor.transformToDocument(content.document);
var myWindow = window.open("data:text/html," + encodeURIComponent(newdoc.documentElement.innerHTML), "_blank", "");
myWindow.focus();
}());
ref: https://gist.github.com/gosub/c7576b0c99ffdd7e993c
You can add the script to apply xslt on xml in the bookmark within parenthesis of 'javascript()'.
Here is the reference: http://www.w3schools.com/xsl/tryit.asp?filename=cdcatalog
Firstly, host the xslt and xml so as to avoid any access issues of files from javascript.
There are some modifications which are needed in the script:
In the reference above, update the following:
xml=loadXMLDoc("cdcatalog.xml");
xsl=loadXMLDoc("cdcatalog.xsl");
to
xml=loadXMLDoc(window.location.href.toString());
xsl=loadXMLDoc("http://<path>/<filename>.xsl");
Save the output in a file as per the output set in your xslt(xml/html/text) or simply display it in alert for copying and using.
Thanks

Resources