Does anyone know how to use hooks or edit Markdown.Editor.js from Pagedown to have it create inline links and instead of referenced ones?
As in, I want this to happen when I click the link button:
[inline link](http://www.google.com)
![alt text](http://website.com/bear.jpg "title text")
instead of this:
[referenced link][1]
![referenced image][2]
[1]: http://google.com/
[2]: http://website.com/bear.jpg "title text"
Thanks!
For reference: https://code.google.com/p/pagedown/
Unfortunately, there do not appear to be any hooks for this functionality in Markdown.Editor.js. I was however able to find the section of code responsible for this, and create a patch for your desired functionality.
Open Markdown.Editor.js in your editor of choice.
Find this section of code:
var linkDef = " [999]: " + properlyEncoded(link);
var num = that.addLinkDef(chunk, linkDef);
chunk.startTag = isImage ? "![" : "[";
chunk.endTag = "][" + num + "]";
Replace with this code:
chunk.startTag = isImage ? "![" : "[";
chunk.endTag = "](" + properlyEncoded(link) + ")";
Profit!
Get a copy
Open a file Markdown.Converter.js
Scroll to the line 724
Edit method function _DoImages(text) {}
Scroll to the line 581
Edit method function _DoAnchors(text) {}
Finally you can achieve absolutely any imaginable results with editing the source code.
UPD:
Just for fun the patch (if you prefer the patches):
converter.hooks.chain("postConversion", function (text) {
var anchors = [];
// definitions
text = text.replace(/\[(\d+)\]\: (htt.+)\n/gi, function(anchor_definition){
anchors.push(anchor_definition.match(/(htt.+)\n/i)[1]);
return("");
});
// anchors in the text
text = text.replace(/\]\[\d+\]/gi, function(anchor){
var id = parseInt(anchor.match(/\d+/)[0]);
var code = "][" + (anchors[id - 1]) + "]";
return(code);
});
return(text);
});
Related
For a course assignment, I'm tasked with 'fixing' an instagram-like page that isn't working properly.
I need to render the hashtags from a tags list by creating an 'a' tag and an 'li' tag. eg. '#beachday (4)'
this is my (unsuccessful) code currently:
I assume the tags should show up with the photos that have been rendered on the page.
function renderTags (tags) {
var tagList = $('.tag-list ul');
tags.forEach(function (tag)
var a = $('<a>').text('#' + tag.tags + '(' + tag.tag_count + ')');
var li = $('<li>').addClass('u-pull-left');
li.append(a);
tagList.append(li);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>Missing HTML here perhaps?</div>
I'm only beginning to learn CSS/html/jQuery so any help understanding where I'm wrong, or a point to any resource (looked at jQuery docs) is greatly appreciated.
~thank you
As I write the javascript code, the LiveServer webpage should reflect the code and changes and at the moment none of my edits have produced results.
1.Ensure the forEach method is properly wrapped in brackets
2.Attach the 'href' attribute to the 'a' tag to make it clickable
function renderTags (tags) {
var tagList = $('.tag-list ul');
tags.forEach(function (tag) {
var a = $('<a>').text('#' + tag.tags + '(' + tag.tag_count + ')');
a.attr('href', '#');
var li = $('<li>').addClass('u-pull-left');
li.append(a);
tagList.append(li);
});
}
I created a map using Leaflet with clusters. I wanted to add a popup when you click the cluster and it will show a popup list of names of the markers inside the cluster. I found a code and it does exactly what I’m looking for: a list popup showing the names of the markers inside the cluster and when you click on the different names on the popup list the related marker popup appears. But when I added the code to my project, I get the error, “reference error onclick is not defined” and the function won't run. I research this error and I found it’s not good practice to use the onclick function in my javascript/HTML in the way the code is written. My question is, how do I rewrite the script to work the way the example I’m using. Here’s a link to the example I’m using to show what I’m trying to accomplish (and this example works when I download it and run it…no error) - http://www.digital-geography.com/working-with-clusters-in-leaflet-increasing-useability/. And I also included my script. Any help on how to make this work will greatly be appreciated. Or, I’m open to achieve this in a different way. Thanks in advance!
function openPopUp(id, clusterId){
map.closePopup(); //which will close all popups
map.eachLayer(function(layer){ //iterate over map layer
if (layer._leaflet_id == clusterId){ // if layer is markerCluster
layer.spiderfy(); //spiederfies our cluster
}
});
map.eachLayer(function(layer){//iterate over map rather than clusters
if (layer._leaflet_id == id){// if layer is marker
layer.openPopup();
}
});
markers.on('clusterclick', function(a){
if(a.layer._zoom == 6){
var myText = '<ul>';
for (feat in a.layer._markers){
myText += '<li><u onclick="openPopUp"(' + a.layer._markers[feat]._leaflet_id + ',' + a.layer._leaflet_id + ')>' + a.layer._markers[feat].feature.properties['cityName2'] + ',' + a.layer._markers[feat].feature.properties['cityName2'] + '</u></li>';
}
myText += '</u>';
var popup = L.popup().setLatLng([a.layer._cLatLng.lat,a.layer._cLatLng.lng]).setContent(myText).openOn(map);
}
})
Because .setContent can accept an HTMLElement rather than just an HTML string, all you need to do is pass in an element with the listener attached, instead of the HTML string - construct the elements explicitly with createElement, and use addEventListener on the element you want to attach the listener to:
markers.on('clusterclick', function(a) {
if (a.layer._zoom !== 6) return;
const ul = document.createElement('ul');
a.layer._markers.forEach(({ _leaflet_id, feature }) => {
const { cityName2 } = feature.properties;
const li = ul.appendChild(document.createElement('li'));
const u = li.appendChild(document.createElement('u'));
u.addEventListener('click', () => openPopUp(_leaflet_id, a.layer._leaflet_id));
u.textContent = cityName2 + ',' + cityName2;
});
const popup = L
.popup()
.setLatLng([a.layer._cLatLng.lat, a.layer._cLatLng.lng])
.setContent(ul)
.openOn(map);
})
I am trying to create a general function that will extract a div content (with nested elements) and save it locally in an HTML file.
Basically I get the div innerHTML, wrap it in html/head/body tags and then save it:
function div2html() {
var inner=document.getElementById("div2save").innerHTML;
var html="<html><head></head><body>"+inner+"</body></html>";
saveTextAsFile("div2html.html", html);
}
See a working version here: jsfiddle
However I am not sure how to handle classes. As you can see the class in the sample (bigbold) is not embedded in the new HTML. I need some way to get all the classes used in the div and then add them (or the computed styles ?) to the html I generate .. is this possible ? is there any other way around it ?
Try including style element .outerHTML within saved html
function div2html() {
var inner=document.getElementById("div2save").innerHTML;
var style = document.getElementsByTagName("style")[0].outerHTML;
var html="<html><head>"+style+"</head><body>"+inner+"</body></html>";
saveTextAsFile("div2html.html", html);
}
jsfiddle http://jsfiddle.net/fb6s763w/1/
Alternatively, using window.getComputedStyle() to select only css of #div2save child node
function div2html() {
var inner = document.getElementById("div2save");
var style = window.getComputedStyle(inner.children[0]).cssText;
var html = "<html><head><style>"
+ "." + inner.children[0].className
+ "{" + style + "}"
+ "</style></head><body>"
+ inner.innerHTML + "</body></html>";
saveTextAsFile("div2html.html", html);
}
jsfiddle http://jsfiddle.net/fb6s763w/2/
Looks like this might be able to help you out:
https://github.com/Automattic/juice
If the CSS of the page is not big, a simple solution is to include it all in the saved html as suggested by guest271314 above with
var style = document.getElementsByTagName("style")[0].outerHTML;
see jsfiddle
A more comprehensive solution extracts the classes from the div and then adds only the rules of those classes to the div (Using code from How do you read CSS rule values with JavaScript?)
function div2html(divId) {
var html = document.getElementById(divId).innerHTML;
// get all css classes in html
var cssClasses = [];
var classRegexp = /class=['"](.*?)['"]/g;
var m;
while ((m = classRegexp.exec(html))) cssClasses = cssClasses.concat(cssClasses, m[1].split(" "));
// filter non unique or empty cssClasses
cssClasses = cssClasses.filter(function (item, pos, self) {
return item && self.indexOf(item) == pos;
});
// get html of classes
var cssHtml = '';
for (var i = 0; i < cssClasses.length; i++) cssHtml += getRule('.' + cssClasses[i]);
// assemble html
var html = "<html><head><style>" + cssHtml + "</style></head><body>" + html + "</body></html>";
console.log(html);
saveTextAsFile("div2html.html", html);
}
see jsfiddle
I could hardly found an easier example but for some unknown reason i have problems with this few lines of code. I dynamically create buttons and add them to my container to the end.
I don't know why but only the first button is added. Please help
Code:
var buttonCount = this.getFoldersContainer().query('button').length;
var button = Ext.create('Ext.button.Button');
button.id = 'folderButton' + record.get('id');
button.setText(record.get('name') + " >>");
console.debug('count');
console.debug(buttonCount);
this.getFoldersContainer().insert(buttonCount,button);
I created a new blank project with only this functionality and it works fine. I don't have a clue what could be causing this in my existing project.
First you should be sure that all buttons get a application wide unique id!
Next is that the id should be present at construction time of the button (in your case it will not be critical but I recommend it). It makes no sense when you are saying that add() would insert at the beginning, because it always insert at the end!
// ....getFoldersContainer().query('button').length; // count all the items!!
// you may do a check if the id is unique while debugging
if(Ext.getCmp('folderButton' + record.get('id')) != null)
console.error('Id duplicated! >> ','folderButton' + record.get('id'))
var ct = this.getFoldersContainer(),
itemCount = ct.items.getCount(),
button = Ext.create('Ext.button.Button', {text:record.get('name') + " >>",id:'folderButton' + record.get('id')});
ct.insert(itemCount > 0 ? --itemCount : itemCount ,button);
// if you just want to insert at the end you will be fine with
// ct.add(button);
I'm using http://rockycode.com/blog/jquery-plugin-readmore/ for trim long text and add a "See more" link to reveal all the text.
I would love to avoid cutting words, how could I do that?
If the limit is 35, don't cut the w...
but
If the limit is 35, don't cut the word... (and in this case, trim it at 38 and then show the hidden text from 39th chtill the end.
Instead of doing this:
$elem.readmore({
substr_len: 35
});
You could do this
$elem.readmore({
substr_len: $elem.text().substr(0, 35).lastIndexOf(" ")
});
What we're doing is to go to the latest space posible before index 35.
Of course 35 can be variable. Also you could put it into a function to reuse it.
Hope this helps
You can change the abridge function within that plugin as follows:
function abridge(elem) {
var opts = elem.data("opts");
var txt = elem.html();
var len = opts.substr_len;
var dots = "<span>" + opts.ellipses + "</span>";
var charAtLen = txt.substr(len, 1);
while (len < txt.length && !/\s/.test(charAtLen)) {
len++;
charAtLen = txt.substr(len, 1);
}
var shown = txt.substring(0, len) + dots;
var hidden = '<span class="hidden" style="display:none;">' + txt.substring(len, txt.length) + '</span>';
elem.html(shown + hidden);
}
...and it will behave as you desire. You might want to add an option to turn this feature off and on, but I'll leave that up to you.
See working example →
I was just gathering information about this subject, with your help and the help from other related posts I wrote this:
http://jsfiddle.net/KHd6J/526/