Adding a target="_blank" with execCommand 'createlink' - javascript

I am attempting to create a mini WYSIWYG editor for a custom CMS. It has the option to add and remove links. It adds links fine, but would like to have the option to add target="_blank" to the hyperlink. Also, if possible, I would like to be able to add alt="" and title="".
At the moment this is my code:
function addLink() {
var linkURL = prompt('Enter a URL:', 'http://');
editorWindow.document.execCommand('createlink', false, linkURL);
}
Been looking around, and can't seem to find a solution. Most of the solutions I've seen say to add:
function addLink() {
var linkURL = prompt('Enter a URL:', 'http://');
var newLink = editorWindow.document.execCommand('createlink', false, linkURL);
newLink.target = "_blank";
}
But this doesn't seem to work. Any suggestions?

I was able to find a solution. Don't know if this is the right way to go, but it works. Following https://stackoverflow.com/a/5605841/997632, this is what I used for my code to work:
function addLink() {
var linkURL = prompt('Enter a URL:', 'http://');
var sText = editorWindow.document.getSelection();
editorWindow.document.execCommand('insertHTML', false, '' + sText + '');
}
Just in case anyone else is looking and stumbles upon this...

insertHTML can be frustrated if you have a bold or italic before.
I use the following approach:
var url = 'example.com';
var selection = document.getSelection();
document.execCommand('createLink', true, url);
selection.anchorNode.parentElement.target = '_blank';

I know this thread is quite old, but let me throw my 2 cents in, and maybe someone will find this useful ;)
I'm working on a WYSIWYG editor too As I found the accepted solution fails for me when I try to make a link from a selected image in FF (the getSelection().getRangeAt(0) returns the image's parent div and treats the image as it never wasn't there (this is how I see it)), here's a dirty but working (and, I think, it's turbo-cross-browser) idea I came up with (jQuery):
//somewhere before losing the focus:
sel = window.getSelection().getRangeAt(0);
//reselecting:
window.getSelection().addRange(sel);
//link:
document.execCommand('createLink', false, 'LINK_TO_CHANGE');
$('a[href="LINK_TO_CHANGE"').attr('target', '_blank');
//any other attr changes here
$('a[href="LINK_TO_CHANGE"').attr('href', theRealHref);
Is it good idea? Works like a charm. And this simplicity ^^

Since, there is no straightforward cross-browser solution, one cross-browser workaround could be programatically attaching an event handler to a inside your editor:
var aLinks = Array.prototype.slice.call(editorElement.querySelectorAll('a'));
aLinks.forEach(function(link) {
link.addEventListener('click', function() {
window.open(link.href, '_blank');
});
});

Nobody seems to mention that as per specs, the document has to be in the design mode:
document.designMode = "on";
Then the following should work:
var url = 'http://google.com';
var selection = document.getSelection();
document.execCommand('createLink', true, url);

The execCommand'createLink' does not always work. It will sometimes wrap the link text inside a link.
i.e
<a>label</a>
Resulting the html link code appearing in the document and the link not working.
in this case ues execCommand 'insertHTML'
val=``+label+``
//document.execCommand('createLink', false, val);
document.execCommand('insertHTML', false, val);

Related

Adding rest of URL before shortened links

I'm creating a Chrome extension for a browser game and one of the features I'd like to add is a floating "latest posts from the forum" window to the right of the game. I've gotten it displaying the way I want it to but, all of the links pulled from the forum are shortened and don't include the full URL. When I click on one of the links it tries to go to that page on the games site rather than the forum site. What I'd like is for my code to fix the URL as well as add a target blank attribute so the links open in a new page/tab. My existing code is below.
$(function(){
var hzsforumpostsss = document.getElementById('latestpostsHZ');
hzsforumpostsss.insertAdjacentHTML('afterend', '<div><div id=\"hzlatestforumss\" style=\"background-color: rgba(0, 110, 187, 0.9);position:absolute;left:50%;width:280px;margin-left:390px;font-size:9pt;display:block;overflow:auto;\"></div></div>');
$('#hzlatestforumss').load('https://cors-anywhere.herokuapp.com/http://heroes-rising-forum.2349640.n4.nabble.com/');
})
Since you're just loading the content directly into your div with some AJAX, you're going to need to loop through all the links in the div and prepend the hostname to the ones which are relative. Your mix of jQuery and vanilla JS is a little confusing, but I'll just stick to vanilla JS for my example code.
[...document.getElementById('hzlatestforumss').getElementsByTagName('a')].forEach(anchor => {
if (anchor.href && !anchor.href.includes('://')) {
if (!anchor.href.startsWith('/')) { anchor.href = '/' + anchor.href; }
anchor.href = 'http://heroes-rising-forum.2349640.n4.nabble.com' + anchor.href;
}
});
You can also add the _blank target in the same loop if you want.
THANK YOU for getting me on the right track! The code I ended up with is below.
$(function(){
var hzsforumpostsss = document.getElementById('latestpostsHZ');
hzsforumpostsss.insertAdjacentHTML('afterend', '<div><div id=\"hzlatestforumss\"'+
'style=\"background-color: rgba(0, 110, 187, 0.9);position:absolute;left:50%;width:280px;margin-left:390px;display:block;overflow:auto;\"></div></div>');
$('#hzlatestforumss').load('https://cors-anywhere.herokuapp.com/http://heroes-rising-forum.2349640.n4.nabble.com/');
setTimeout(function(){
$('a[href*="/"]').each(function(){
var current = $(this).attr("href");
$(this).attr("href", "http://heroes-rising-forum.2349640.n4.nabble.com" + current);
$(this).attr("target", "_blank");
});
},2000);
})
Something like this?
$(function(){
var hzsforumpostsss = document.getElementById('latestpostsHZ');
hzsforumpostsss.insertAdjacentHTML('afterend', '<div class="HideFJcontainer" style=\"position:absolute;left:50%;width:280px;margin-left:390px;display:block;overflow:auto;\">'+
'<input type="checkbox" class="HideFJforum"> Hide/Show Forum<div id=\"hzlatestforumss\"></div></div>');
$('#hzlatestforumss').load('https://cors-anywhere.herokuapp.com/http://heroes-rising-forum.2349640.n4.nabble.com/',
function(){
$('a[href*="/"]').each(function(){
var current = $(this).attr("href");
$(this).attr("href", "http://heroes-rising-forum.2349640.n4.nabble.com" + current);
$(this).attr("target", "_blank");
});
} );

How to set class using execCommand?

Hello I have the following to set a link:
function iLink() {
var linkURL = prompt("Enter the URL for this link:", "http://");
richTextField.document.execCommand("CreateLink", false, linkURL);
This works but i want to change the class of the link, so i tried:
var linkURL = prompt("Enter the URL for this link:", "http://");
richTextField.document.execCommand("CreateLink", false, linkURL);
var listId = window.getSelection().focusNode.parentNode;
$(listId).addClass("alink");
But that didnt work, have I done something wrong with the above code or is their another way i can implement a class name?
You probably don't have jquery loaded on the page, and you don't need jquery anyway.
Try:
richTextField.getSelection().focusNode.parentNode.classList.add("alink");

Jquery attr('src') undefined in IE 8 (works in FF)

This has gotten so far,that I will sum up what we found out:
Inside the event handler the attribute src cannot be read in IE8 (FF works fine), neither with jQuery nor with usual javascript
The only way to get the data was to get it outside the handler, write it to an array and read it afterwards from the inside of the handler
But there was still no possibility to write to src (neither jQuery nor javascript worked - only for IE 8)
I've got it working by writing the img elemts themselves to the document, but the reason behind this problem is no solved
The snippet we have is used twice.
The old code
<script type="text/javascript">
jQuery(document).ready(function() {
//...
//view entry
jQuery('.blogentry').live('click',function(){
// Get contents
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
imgleft = jQuery(this).children('.Image_left').attr('src');
imgcenter = jQuery(this).children('.Image_center').attr('src');
imgright = jQuery(this).children('.Image_right').attr('src');
// Write contents
jQuery('#bild_left').attr('src', imgleft);
jQuery('#bild_center').attr('src', imgcenter);
jQuery('#bild_right').attr('src', imgright);
jQuery('.person').attr('src', profileimage);
jQuery('#g_fb_name').html(blogauthor);
jQuery('#g_titel').html(blogtitle);
jQuery('#g_text').html(blogtext);
//...
});
//...
// Change entry
jQuery('.blogentry').each(function(){
entryindex = jQuery(this).attr('rel');
if (entry == entryindex)
{
// The following works fine (so 'children' works fine):
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
// This does not work - only in IE 8, works in Firefox
imgleft = jQuery(this).children('.Image_left').attr('src');
imgcenter = jQuery(this).children('.Image_center').attr('src');
imgright = jQuery(this).children('.Image_right').attr('src');
//alert: 'undefined'
alert(jQuery(this).children('.Image_center').attr('src'));
//...
}
}
//...
});
</script>
The new code
Please see my own posted answer for the new code.
UPDATE:
This does not work if called inside of the click event!!!
jQuery('.Image_left').each(function(){
alert(jQuery(this).attr('src'));
});
SOLUTION TO GET THE IMAGE DATA:
relcounter = 1;
imgleft_array = new Array();
jQuery('.Image_left').each(function(){
imgleft_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgcenter_array = new Array();
jQuery('.Image_center').each(function(){
imgcenter_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgright_array = new Array();
jQuery('.Image_right').each(function(){
imgright_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
//... inside the eventhandler (entryindex = 'rel' of blogentry):
imgleft = imgleft_array[entryindex];
imgcenter = imgcenter_array[entryindex];
imgright = imgright_array[entryindex];
This works because it is not called inside the event handler and the sources are saved beforehand
BUT! I still cannot write the data, which is my aim:
jQuery('#bild_left').attr('src', imgleft);
jQuery('#bild_center').attr('src', imgcenter);
jQuery('#bild_right').attr('src', imgright);
UPDATE!!!
This is just crazy, I tried to write the data via usual javascript. This also works in FF, but no in IE8. Here really is some serious problem witt the attribute src:
document.getElementById('bild_left').src = imgleft;
document.getElementById('bild_center').src = imgcenter;
document.getElementById('bild_right').src = imgright;
alert(document.getElementById('bild_left').src);
This works in FF, but not in IE8, the attribute src remains undefined after writing! This seems to be not a jQuery problem at all!
children looks for immediate child elements only where as find looks for all the elements within it until its last child element down the dom tree. If you are saying find is working that means the element you are looking is not its immediate children.
Try to alert this jQuery(this).children('#Image_center').length see what you get.
FYI. Even when any element is not found jQuery will return an emtpy object it will never be null. So alert an emtpy object will always give you [object Object]. You should alwasy check for the length property of the jQuery object.
Try this
alert(jQuery(this).find('#Image_center').length);//To check whether element is found or not.
Bing Bang Boom,
imgright = jQuery(".Image_right",this).attr('src');
And why don't you easily use one working?
alert(jQuery(this).children('#Image_center').attr('src'));
change children to find
alert(jQuery(this).find('#Image_center').attr('src'));
It is probably the easiest solution, and when it work, why wouldn't you use it?
the problem is not in the attr('src') but in something else. The following snippet works in IE8:
<img id="xxx" src="yrdd">
<script type="text/javascript">
alert($('#xxx').attr('src'));
</script>
But if you for example change the the text/javascript to application/javascript - this code will work in FF but will not work in IE8
This has gotten so far,that I will sum up what we found out:
Inside the event handler the attribute src cannot be read in IE8 (FF works fine), neither with jQuery nor with usual javascript
The only way to get the data was to get it outside the handler, write it to an array and read it afterwards from the inside of the handler
But there was still no possibility to write to src (neither jQuery nor javascript worked - only for IE 8)
I've got it working by writing the img elemts themselves to the document, but the reason behind this problem is no solved
The new code
relcounter = 1;
imgleft_array = new Array();
jQuery('.Image_left').each(function(){
imgleft_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgcenter_array = new Array();
jQuery('.Image_center').each(function(){
imgcenter_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgright_array = new Array();
jQuery('.Image_right').each(function(){
imgright_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
//view entry
jQuery('.blogentry').live('click',function(){
// Get contents
entryindex = jQuery(this).attr('rel');
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
imgleft = imgleft_array[entryindex];
imgcenter = imgcenter_array[entryindex];
imgright = imgright_array[entryindex];
// Write contents
jQuery('#entryimages').html('');
jQuery('#entryimages').html('<img class="rotate" width="132" height="138" id="bild_left" src="'+imgleft+'" /><img class="rotateright" width="154" height="162" id="bild_center" src="'+imgcenter+'" /><img class="rotate" width="132" height="138" id="bild_right" src="'+imgright+'" />');
jQuery('.person').attr('src', profileimage);
jQuery('#g_fb_name').html(blogauthor);
jQuery('#g_titel').html(blogtitle);
jQuery('#g_text').html(blogtext);
});
So I am just not using .attr('src') in the event handler....
Try to make a delay:
jQuery(document).ready(function() {
setTimeout(function () {
jQuery('.blogentry').each(function(){
// your code...
});
}, 100); // if doesn't work, try to set a higher value
});
UPDATE
Hope, this code will work.
$('.blogentry img').each(function(){
alert( $(this).attr('src') );
});
UPDATE
I'm not sure, but maybe IE can't read classes with uppercase first letter...
Try to change ".Image_center" to ".image_center"
UPDATE
Check your code again. You definitely have some error. Try this jsfiddle in IE8, attr('src') is showed correctly. http://jsfiddle.net/qzFU8/
$(document).ready(function () {
$("#imgReload").click(function () {
$('#<%=imgCaptcha.ClientID %>').removeAttr("src");
$('#<%=imgCaptcha.ClientID %>').attr("src", "Captcha.ashx");
});
});

I need to set display: block on div then find an anchor within that div

I'm nearly finished with this project but I have been beating my head against this problem for a day or so.
Big picture:
Im trying to create a link that will jump between tabs and find an anchor.
Details:
I need to create a link which triggers the function that hides the current div (using display: none)/shows another div (display: block;) and then goto an anchor on the page.
My first intuition was to do:
code:
<a onClick="return toggleTab(6,6);" href="#{anchor_tab_link_name}">{anchor_tab_link_name}</a>
Since the onClick should return true and then execute the anchor. However it loads but never goes to the anchor.
Here is the toggleTab function to give some context:
function toggleTab(num,numelems, anchor, opennum,animate) {
if ($('tabContent'+num).style.display == 'none'){
for (var i=1;i<=numelems;i++){
if ((opennum == null) || (opennum != i)){
var temph = 'tabHeader'+i;
var h = $(temph);
if (!h){
var h = $('tabHeaderActive');
h.id = temph;
}
var tempc = 'tabContent'+i;
var c = $(tempc);
if(c.style.display != 'none'){
if (animate || typeof animate == 'undefined')
Effect.toggle(tempc,'appear',{duration:0.4, queue:{scope:'menus', limit: 3}});
else
toggleDisp(tempc);
}
}
}
var h = $('tabHeader'+num);
if (h)
h.id = 'tabHeaderActive';
h.blur();
var c = $('tabContent'+num);
c.style.marginTop = '2px';
if (animate || typeof animate == 'undefined'){
Effect.toggle('tabContent'+num,'appear',{duration:0.4, queue:{scope:'menus', position:'end', limit: 3}});
}else{
toggleDisp('tabContent'+num);
}
}
}
So I posted this on a coding forum and a person told me that my tab code was done in prototype.
And that I should "Long story short: don't use onclick. Attach the data to the A tag and handle the click event yourself (using preventDefault() or similar) to do your tab-setting stuff, then when it's done, manually set your location to the hash tag."
I do understand what he is suggesting but I don't know how to implement it because I don't know much about javascript syntax.
If you can provide any hints or suggestions it would be amazing.
Update:
I tried to implement the solution below like this:
The link:
<a id="trap">trap</a>
Then adding the following js to the top of the page:
<script type="javascript">
document.getElementById("trap").click(function() { // bind click event to link
tabToggle(6,6);
var anchor = $(this).attr('href');
//setTimeout(infoSupport.gotoAnchor,600, anchor);
jumpToAnchor();
return false;
});
//Simple jump to anchor point
function jumpToAnchor(){
location.href = location.href+"#trap";
}
//Nice little jQuery scroll to id of any element
function scollToId(id){
window.scrollTo(0,$("#"+id).offset().top);
}
</script>
But unfortunately it simply doesn't seem to work for me. When I click the text simply nothing happens.
Anyone notice any apparent mistakes? I'm not used of working with javascript.
I found a lot simpler solution:
$(function(){
jumpToTarget('spot_to_go'); //This is what you put inside your function when the link is clicked.
function jumpToTarget(target){
var target_offset = $("#"+target).offset();
var target_top = target_offset.top;
$('html, body').animate({scrollTop:target_top}, 500);
}
});
Working demo:
http://jsbin.com/ivure/3/edit
So on the click event you do something like this:
//Untested
$('#trap').click(function(){
tabToggle(6,6);
var anchor = $(this).attr('href');
jumpToTarget(anchor);
return false;
});
​
Apparently a small delay was all I needed.
I used this for the link. This is preferred for my situation since I'm batch generating many of these links.
trap
Then I used this vanilla javascript
//Simple jump to anchor point
function jumpToAnchor(target){
setTimeout("window.location.hash=target",450);
}
This loads the link and instantly goes to the location. No jerkiness or anything.

Code isn't compatible with IE?

$(document).ready(function() {
var url = document.location.toString();
$('.tab').click(function() {
if($(this).is(".active")) {
return;
}
var classy = $(this).attr("class").split(" ").splice(-1);
var innerhtml = $('.content.'+classy).text();
$('#holder').html(innerhtml);
$('.tab').removeClass('active');
$(this).addClass('active');
});
var url = document.location.toString();
if(url.match(/#([a-z])/)) {
//There is a hash, followed by letters in it, therefore the user is targetting a page.
var split = url.split("#").splice(-1);
$('.tab.'+split).click();
}
else {
$('.tab:first').click();
}
});
Hey, I was just informed by one of my commenters that this code doesn't work in IE. I can't for the life of me figure out why. Whenever you switch tabs, the content of the tab doesn't change. Meanwhile the content of the #holder div is all the tabs combined.
Any ideas?
Not the answer you're after, but I'd seriously recommend looking into the jQueryui tabs widget if you can. It's made my life a lot easier dealing with this stuff at least.
Hard to tell without an IE version and a page to look at what exactly is happening- but here are some best guesses:
change:
if($(this).is(".active")) {
to:
if($(this).hasClass("active")) {
change:
var innerhtml = $('.content.'+classy).text();
to:
var innerhtml = $('.content .'+classy).text(); // note the space
change:
var url = document.location.toString();
to:
var url = document.location.hash;
I did all changes which Ryan suggested except adding the space between '.content' and the period as it is needed. He could not have known without the source code.
I changed your .splice(-1) to [1] so that I'm choosing the second item in the array, which is the class name. It looks like .splice(-1) is behaving differently in IE and other browsers.
I have tested the code with IE 7-8 and it works.
Source code as it is now:
$(document).ready(function() {
var url = document.location.hash;
$('.tab').click(function() {
if ($(this).hasClass("active")) {
return;
}
var classy = $(this).attr("class").split(" ")[1];
var innerhtml = $('.content.' + classy).text();
$('#holder').html(innerhtml).slideDown("slow");
$('.tab').removeClass('active');
$(this).addClass('active');
});
if (url.match(/#([a-z])/)) {
//There is a hash, followed by letters in it, therefore the user is targetting a page.
var split = url.split("#")[1];
$('.tab.' + split).click();
}
else {
$('.tab:first').click();
}
});

Categories

Resources