Programmatically turning on <strong></strong> for editable section in html5 - javascript

I am working on an HTML5/javascript/php project where I have a which is set to be editable.
I know the user can be press ctrl + b to make the text bold, but I also want to allow the user to be able to click on the appropriate button on the web page to perform the same action.
I.e. when the user types it will be in normal text, they click on the bold button on the web page and it appends <strong> to the html of the section, and whatever they type now will be hold until they press the button again and it then appends </strong>.
However, at the moment when I append <strong> it seems to automatically add </strong> and I want to stop that from happening. Am I going about this the right way or is there a better way that this can be achieved.
Below is the javascript that I am trying to use
function enableDisableBold(section)
{
var boldEnabled = $("#boldEnabled").val();
var content = $("#" + section).html();
var newContent;
if (boldEnabled == "true")
{
$("#btnBold").removeClass("formatButtonsActivated");
$("#boldEnabled").val("false");
//newContent = content + "</strong>";
//$("#" + section).html(newContent);
}
else
{
$("#btnBold").addClass("formatButtonsActivated");
$("#boldEnabled").val("true");
newContent = content + "<strong>";
$("#" + section).html(newContent.replace("</strong>", ""));
}
alert($("#" + section).html());
}
Thanks for any help you can provide.
UPDATE
I've just come across another solution which does what I want to achieve, but there is a slight issue. At the end of the function call, I perform the following bit of code.
var article = document.getElementById(section);
article.focus();
document.execCommand("Bold", false, null);
The problem is this is working fine in Internet Explorer, but in Chrome is where I am having the problem. When I set the focus back to the <section> tag, it puts the cursor back to the beginning of the text. I read somewhere that putting onfocus="this.value = this.value;" on the control but this doesn't help.
I was trying to find a way of putting the cursor back to the end of the character, but I would actually need to put the cursor back to where it originally was. Is this something that can be done.

create a strong element and append your content to it
$('<strong />').append(content);

Related

Control + F similar text search box to embed in website for iframe

So I have a long iframe in my website full of text. Iframe is from an other domain that I don't own so I have no control over this embedded iframe. What I do when I want to search a part of text in this iframe is to click CTRL+F and it will find the needed text and jump on that part of the iframe.
That was ok for as long as I used this page only for myself. Now that many people are accessing this iframe i can not explain the functionality of CTRL+F to everybody. So I was thinking to embed a Text search in this page where the iframe is so it will be easier for people to find what they want.
I tried many suggestions by this site but they don't really work with iframe since they search words in the page where the iframe is embedded. How CTRL+F can detect text from iframe? Is it possible to have same functionality embedded in my website?
Thank you
Did this other day using only Javascript maybe not the most efficient as it reads and re-writes the inner html onkeyup (so i had to make some regex to ignore tags) but it works and is quick let me know if you have any improvements.
I tried to put it in codepen but as it f**ks with innerhtml so it doesnt work but this might be up for a while:http://longstone.rocks/Cinturato/fitment-guide/
Note---id:matches is a <\p> under my search telling the user how many matches it found
<script>
function Search(){
//clear everyting
document.getElementById("matches").innerHTML = "Type to find your car!";
document.getElementById("main-content").innerHTML = document.getElementById("main-content").innerHTML.replace(/<span.+?>(.+?)<\/span>/g,'$1');
if (document.getElementById("textbox").value !== ""){
alert();
//this regegex basically matches all pattern exept from when its inbetween < and >
var searchterm = ("(?<!</?[^>]*|&[^;]*)(" + document.getElementById("textbox").value + ")");
var regex = new RegExp(searchterm,"gi");
w3.addClass('textarea', 'w3-border-red');
//if there is no match then it breaks in this following line when i want it to return 0 rather than break
var numberOfMatches = document.getElementById("main-content").innerHTML.match(regex).length;
alert(numberOfMatches);
alert("fdfd");
document.getElementById("main-content").innerHTML = document.getElementById("main-content").innerHTML.replace(regex,'<span class="w3-aqua">$1</span>');
document.getElementById("matches").innerHTML = numberOfMatches + " Matches highlighted scroll to see matches";
if(numberOfMatches !== 0)
w3.removeClass('textarea', 'w3-border-red');
}
else
w3.addClass('textarea', 'w3-border-red');
}
</script>

What's the best way to append html tags to existing text?

I want to use the currently selected text in the office document to be replaced by the same selected text but surrounded with html. Effectively adding a hyperlink to the current selection.
I first read the text property of the selection
var objRange = objContext.document.getSelection();
objRange.load('text');
followed by
return objContext.sync().then(function(){
var strSelection = objRange.text;
objRange.insertHtml(
"<a href='" + decodeURIComponent(strHyperlink) + "'>" + strSelection + "</a>",
Word.InsertLocation.replace
);
return objContext.sync().then(function(){
objDialog.close();
});
});
I need a sync to read the text and then another one to write the updated text back into the document after that I close a dialog. But this sometimes causes the html to get written into the document twice. Is there a better way of doing this instead of with double context syncs?
To answer your question, if you need to read the text and then write into a different context, you'll need two syncs.
But you might take a look at the Range.hyperlink property, which is writeable. I don't know if it'll give you a way to avoid two syncs, but is intended for what you seem to be using insertHtml to do.

document.body.innerHTML issue

I have an email converter on a website that was written by another developer that takes a person’s user name and formats it to an email address.
If you type on a page [[username]] it will generate a clickable email address on the webpage: username#gmail.com
Now I am trying to incorporate PayPal’s skip to accessibility navigation to the website.
After I add the code for Pay Pal, when I press tab the "Skip to" link appears at the top left, but the link doesn’t work. Meaning the dropdown menu will not appear.
https://github.com/paypal/skipto
In my javascript email converter there is a code line
document.body.innerHTML = emailConvert(document.body.innerHTML);
This seems to be the the issue, because the Paypal code also is using innerHTML in their code as well.
I’m looking for a solution for this specific line of code or all of the code
document.body.innerHTML = emailConvert(document.body.innerHTML);
I have tried various solutions with no results. Any help would be great.
Here is the code:
$(document).ready(function () {
(function () {
var domains = { 'n': 'gmail.com', 'p': 'yahoo.com', 's': 'comcast.net', 'k': 'att.net', 'b': 'aol.com', 'i': 'sbcglobal.net' };
function renderEmail(str, user, domain, text) {
var email = (user.match(/#/)) ? user : user + "#" + (domain || domains["n"]);
if (domains[user.toLowerCase()]) { email = domain + "#" + domains[user.toLowerCase()]; }
return " <a href='mailto:" + email + "?Subject=" + document.title + "\"'>" + (text || email) + "</a>";
}
function emailConvert(source) { return source.replace(/\[\[\s*([^\ [\,\|]*)\|?\s*([a-zA-Z0-9_\.-]+)?\s*()\]\]/g, renderEmail).replace(/\[\[\s*([^\[\,\|]*)\|?\s*([a-zA-Z0-9_\.-]+)?\s*\,{1}\s*([^\]]*)\s*\]\]/g, renderEmail); }
document.body.innerHTML = emailConvert(document.body.innerHTML);
$.fn.emailConverter = function () { this.innerHTML = emailConvert($(this).html(emailConvert($(this).html()))); }
})();
});
innerHTML gives you a string representation of the HTML within an element. It doesn't capture event handlers that were attached to those elements programmatically, since those aren't represented in the HTML.
Don't overwrite the innerHTML of document.body. That's like telling your secretary to write something down, and s/he instead grabs everything on your desk, hurls it out the window, then scrawls the desired note directly on your desktop. Even if the secretary draws a very accurate picture of your phone on the desk, you shouldn't be surprised when it doesn't work.
Okay, not a perfect metaphor, but hopefully you get my meaning.
Instead, you should find the specific HTML element(s) you want to modify, and/or insert new HTML elements at the desired locations.
There are lots of different methods by which you can grab an existing element on the page, such as document.getElementById, document.querySelector, document.querySelectorAll, and document.getElementsByTagName. You can also drill down into the child nodes of document.body if you want to obsessively check all the elements on the page.
Similarly, there are also multiple way to insert HTML into an HTML element once you've selected it, including both appendChild and insertAdjacentHTML. You can still manipulate the innerHTML of a specific element, but you should be careful about overwriting any child nodes it might contain, especially if those child nodes might have event listeners.

Twitter Intent link is not opening in a new window

I have created an interface that allows people to Tweet at certain individuals from a webpage. To do so, I am utilizing Twitter's web intents. At first, the page had a textarea that contained a placeholder tweet that was passed through as a text parameter when a user clicked a Reply button, but the scope has changed so that the user should be able to enter text in the textarea, click the button, and see the Twitter popup with their updated tweet, because user testing showed that people were less likely to tweet at people if they weren't able to edit the content on the page.
The problem is that while this code does update the Twitter intent link, it seems to have broken some functionality of the Twitter intent link. Most notably, the links do not open up in a small popup like they normally do - instead, they replace the current page. Also, the "in_reply_to" functionality is intermittent - certain links that should contain tweets to reply to do not, while others do.
Anyone tried to do anything like this? And if so, any advice? I'm at a loss at this point.
The HTML (we're using Django, hence the template logic):
<div class="response">
{%if quote.tweet_id%}
<textarea id="twitter_response_text" class="has_tweet_id" maxlength="140">{{quote.twitter_handle}} {{quote.twitter_text_default}}</textarea>
<label for="twitter_response_text"><span></span></label>
<a class="hasReply" data-tweet-id="{{quote.tweet_id}}" href="https://twitter.com/intent/tweet?in_reply_to="><button value="respond" data-quote-id="{{quote.id}}"/><img src="{{STATIC_URL}}img/reply_arrow.png"> Reply</button></a>
{%else%}
<textarea id="twitter_response_text" maxlength="140">{{quote.twitter_text_default}}</textarea>
<label for="twitter_response_text"><span></span></label>
<button value="reply" data-quote-id="{{quote.id}}" /><img src="{{STATIC_URL}}img/reply_arrow.png"> Reply</button>
{%endif%}
</div>
Javascript:
$(".response a, .twitteraction a").on("click", function() {
//get text from the textarea of the current slide
var textarea = $(this).parents(".slide").find("#twitter_response_text")
if (textarea.val() !== "") {
text = textarea.val();
} else {
text = textarea.text();
}
//maybe we need the handle?
// var handle = $(this).parents(".slide").find("#twitterhandle").text();
//get the link
var link = $(this).attr("href");
//check to see if it needs reply link or regular
if ($(this).hasClass("hasReply")) {
//get the tweet id, stored as data attribute in the anchor
var tweetId = $(this).data("tweet-id");
//construct the query with a twitter id but no handle
var query = encodeURIComponent(tweetId) + "&text=" + encodeURIComponent(text) + "&related=ForecastFacts&original_referer=http://climatecliff.org/";
//add link to anchor
$(this).attr("href", (link + query));
} else {
//construct the query with text and related
var query = encodeURIComponent(text) + "&related=ForecastFacts&original_referer=http://climatecliff.org/";
//add query to anchor
$(this).attr("href", (link + query));
}
});
Turns out there is a way to remove the dependency on platform.twitter.com for their Javascript by adding it yourself - https://dev.twitter.com/docs/intents
Regarding the intermittent in_reply_to links, for some reason the data I attributes I had were adding 1 to the tweet_id that was being passed in the Django context. I'm not sure why, but I went ahead and refactored my code to only dynamically add the text, rather than the tweet id, since that isn't going to change.
Now it all works just fine.

workaround for ckeditor bug nesting divs bug?

Any suggestions or workarounds for this bug?
http://dev.ckeditor.com/ticket/6436
i really need to get around this bug as i need to delete whole divs with one backspace in the editor area in CKEditor. but on insertion the divs get nested due to the bug. So, deletion of individual divs become impossible.
Here is the workaround i finally designed--
http://thecamelcase.com/2011/06/reining-in-the-cursor-in-ckeditor/
I encountered this same issue and unfortunately the link to the fix made by ghostCoder isn't available anymore.
In addition to nested divs issue, we have forced paste as plain text (so data is pasted as plain text unless "paste from word" is used) and we are using div as our enterMode. In the pasted data line breaks were replaced with <br /> tags whereas we wanted each line to be wrapper inside element.
This our how I eventually solved the issue. You should know that we have not changed autoParagraph config option so it defaults to true and I don't recommend disabling it in config level. I'll try to code comment this solution well so that you get a good idea what is actually done here.
config.on.instanceReady = function(e) {
var enterMode = e.editor.config.enterMode, elem = 'div';
if(enterMode === CKEDITOR.ENTER_P) {
elem = 'p';
}
// We didn't encounter any issues when using br as enterMode so
// continue only if enterMode is div or p element
if(enterMode === CKEDITOR.ENTER_DIV || enterMode === CKEDITOR.ENTER_P) {
// Disable autoParagraph in initialization to avoid nested div issue.
// When autoParagraph is manipulated this way it will still be active
// later on so if you write some inline content in source mode it
// will be properly wrapped inside <p> or <div> element.
e.editor.config.autoParagraph = false;
// Handle paste event to get rid of <br /> line breaks issue
e.editor.on('paste', function(evt) {
var data = '';
// Stop event, handle everything here manually
evt.stop();
// Get data either from event's text or html property
if(evt.data.text) {
// Remove HTML markup from pasted data
data = evt.data.text.replace(/(<([^>]+)>)/ig, '');
// Replace all line breaks with </div><div> or </p><p> markup
// And wrap the whole content inside <div> or <p> element
data = '<' + elem + '>'
+ data.replace(/\r\n|\r|\n/g, '</' + elem + '><' + elem + '>')
+ '</' + elem + '>';
} else {
// If data was not pasted as plain text just
// get data as is from event's html property
data = evt.data.html;
}
// Insert HTML data to editor
evt.editor.insertHtml(data);
// Fire afterPaste manually as we have stopped the event
// and afterPaste wouldn't get triggered otherwise
evt.editor.fire( 'afterPaste' );
}, e.editor.element.$);
}
};

Categories