Updating the state of a button in a text editor - javascript

I'm trying to develop an app for ipad and I'm using the contenteditable feature. I have created 3 buttons (bold, italic, underline) and when someone taps them they perform the functionality using execCommand. However when the user selects a word that is bold I want to change the state of the Bold icon image so that it lets the user know that the selected text is in bold. This feature is available in programs like ckeditor and tinymce but I want to know how it's done. I know that some people use a timer that checks all the states every second but I don't think that's the right way. Could someone help me with the code or explain how this could be done.

look up the document.queryCommandState() method to find your answer
I believe you pass a flag which returns true or false, such as...
if(document.queryCommandState("Bold")){ highlightBoldBtn(); }
EDIT
To clarify, if I understand you correctly this will work. This is how I did it with my editors. Just add a 'onclick' and 'onkeyup' event to your contenteditable div or textarea like the following
// this array is for every button you implement on your editor
var buttonarr = ["Bold", "Italic", "Underline"]
// here is the onclick/keyup function for your element
function updateButtons(){
for(var i=0; i<buttonarr.length; i++){
var buttontype = buttonarr[i];
if(document.queryCommandState(buttontype)){
// call function to turn this button "on" or use jQuery
$('#btn_'+buttontype).addClass('button_on');
}
}
}
If you noticed, what I did was gave each of my buttons the ID of "btn_" with the button flag appended to it. Using CSS I then made a button_on class that styles it accordingly. You may want to simply remove the 'button_on' class from all buttons on each call to updateButtons(), and then add the class back on as it returns true.

Related

Formatting buttons for contentEditable reflect selection formatting

We have a contenteditable="true" div which we use as a wysiwyg text editor. We added a basic formatting toolbar similar to the one that uses Medium.com
Using execCommand(), we're able to make the selected text bold if, for instance, the user presses the bold button. This works great.
However, something we haven't managed to do yet is to make the bold button highlighted if the user selects a part of the text which is in bold, like illustrated in the picture above. This could be easily done by passing a is-active class on the button of course, but how do we know that the selected text is, in this case, bold?
We think it could perhaps be done using the Selection API but this use case seems undocumented.
since the execCommand() use html tag wrappers like B tag for bold .
So when you are selecting the word i am sure you are using some sort of js to show that formating tollbar just add some more code in that function like this.
if(selectedElement.nodeName == "B"){
toolbarBoldButton.classlist.add("is-active");
}
Note: i am using js function "nodeName" to get the tag name which was wrapped around the execCommand() in this case bold/B then matching if it matches the tag and if true i am adding the is-active class to the toolbars Bold style element.

Custom action links in .PDF...write Javascript to alter the appearance of links when clicked?

I have a .pdf document that contains custom links which run Javascript code.
There is no issue with the actual functionality of the working portion of the JS, but I do have one formatting/display problem that I havent been able to solve:
Is it possible to write JS that will alter the appearance of individual links as they are clicked?
I know I can programmatically change the appearance of all links on a page by looping through the doc.getLinks result and applying formatting changes to each element of the getLinks array. But I don't know how to refer to a specific link, as/after it's clicked, either by referencing that link's index location within the getLinks array, or by referring to it by any other name, handle, etc.
I would think that this is probably possible to do, but I'm at a loss.
Thanks in advance for any pointers!
EDIT: One thing to clarify...I can do everything I need to do for a single button. That is, I can manually find the button name, and manually enter the JS code to change the appearance of that particular button. To do this, I need to physically look up the name of the button using a few mouse clicks, and then hard code that button's name in my JS getField command. This requires different code for each and every button.
Is it possible to accomplish the same function using the same code for each and every button?
My ultimate objective is to be able to reproduce this function on a series of .pdf files that will, jointly, have thousands of individual buttons. So any manual component of this process will make implementation impractical.
I should have originally phrased the question in terms of, is it possible to write JS code that can automatically detect the name of the button which is calling the code? (ie, how would I implement a self-referential feature for a generic button?)
As wished by the OP…
When a script should refer to the field on which it is running, the field object to use is event.target.
An example:
You have a button which, when clicked, should change the width of the border between 1 and 3. The mouseUp event would containt this piece of code:
if (event.target.lineWidth == 1) {
event.target.lineWidth = 3 ;
} else {
event.target.lineWidth = 1 ;
}
Or another example: when the number in the calculated text field is negative, it should be in red, otherwise in black:
In the Format event of that field, you would add:
if (event.value*1 < 0) {
event.target.textColor = color.red ;
} else {
event.target.textColor = color.black ;
}
And that should give an idea on how to use event.target.

Calling a click function independently

I'm using the following spell checking javascript. The button that opens the spell checker is defined as button and if a icon, image or text is given the matching id, when this is clicked the spell checker opens.
I want to be able to call the spellchecker directly e.g. onclick="openChecker();" i even tried _openChecker() but cannot seem to call the correct function.
https://raw.github.com/LPology/Javascript-PHP-Spell-Checker/master/spellcheck.js
Can anyone help?
Thanks
The ID property should be unique in the first place so you should not have other elements with the same ID - one of the reasons is what happens to you, you get events triggered when elements with the same ID are clicked. You should fix this and if you do have elements that require the same identificator, you should use a class instead. As for your question you could do something like this:
$("selector").on("click",function(){
//your code here
});

How to prevent multiple html selection box displayed on screen?

I have been working on the last bit of my php + ajax based datagrid project.Everything works as I designed except one thing : I cannot stop user opening multiple selection boxes...
Go my research page and use username "ChenxiMao" and password "accedo" to login(without double quotes).
Note that perhaps the images used in this datagrid would not be displayed when page is loaded for the first time(weird, I am trying to fix this, browser incompatibilities, perhaps).
If you double click on one cell in the "CONSULTANT" column, a html select box would be displayed, you can select one consultant to assign him to this task or unassign the consultant from this task. No problem for this.
The problem is : when user leaves this selection box OPEN, he/she can still open another selection box... My jquery code cannot stop people from opening multiple selection boxes.
You can ctrl-U to see the source code on this page, and check the content inside the "gridview-helper.js" for what I have been done.
I want to let user only open a single selection box. When he/she leaves the cell, the selection box should be closed, without changing the html inside...
Puzzled, screwed up for this afternoon...
Thanks for any suggestons in advance!
JavaScript is single-threaded, so you can add a mutex variable and check its value before opening a new select box.
At the top of gridview-helper.js:
var is_choice_visible = false;
In your double-click handler:
$(this).dblclick(function()
{
if (is_choice_visible)
return;
is_choice_visible = true;
...
For your select box, add an onblur handler which sets is_choice_visible back to false and deletes itself.
Unrelated tip: Growing a string in a loop is slow on older versions of Internet Explorer. It's more efficient to append to an array and join the array, e.g.:
var html = ["<select>..."];
for (var i in consultantnames)
{
html.push("<option>...</option>");
}
html.push("</select>");
return html.join("");
Have you tried using the onmouseout event on the cell, and removing the child dropdown box element if mouse out is triggered? Seems that should work.

Problem getting selected text when using a sprited button and selection.createRange() in Internet Explorer

I'm working on implementing sprited buttons in Stackoverflow's beloved WMD markdown editor and I've run into an odd bug. On all versions of IE, the selected text is lost upon button clicks, so, say, highlighting a block of text and clicking the code button acts like you placed the cursor at the end of the selection and clicked the button.
e.g. highlighting this:
This
Is
Code
and clicking the code button give you:
This
Is
Code`enter code here`
What's really weird is that I left the original non-sprited button bar in and that works just fine. In fact ALL buttons and keyboard shortcuts code use the same doClick(button) function!
Old-style non-sprited buttons: OK
Keyboard shortcuts: OK
Sprited buttons in non-IE browsers: OK
Sprited buttons in IE: WTF
I've isolated the problem down to a call to selection.createRange() which finds nothing only when the sprited button is clicked. I've tried screwing around with focus()ing and making sure as little as possible happens before the doClick() but no joy. The keyboard shortcuts seem to work because the focus is never lost from the input textarea. Can anyone think of a hack that will let me somehow collect the selected text in IE?
The onclick handler looks like this:
button.onmouseout = function(){
this.style.backgroundPosition = this.XShift + " " + normalYShift;
};
button.onclick = function() {
if (this.onmouseout) {
this.onmouseout();
}
doClick(this);
}
I've tried moving the onmouseout call to after the doClick in case that was causing a loss of focus but that's not the problem.
EDIT:
The only thing that seems to be different is that, in the original button code, you are clicking on an image. In the sprited code, you are clicking on a list item <li> with a background image set. Perhaps it's trying to select the non-existent text in my list item?
/EDIT
Actual code is located in my wmd repository on git in the button-cleanup branch.
If you revert to the 0d6d1b32bb42a6bd1d4ac4e409a19fdfe8f1ffcc commit you can see both button bars. The top one is sprited and exhibits the weird behavior. The bottom one contains the remnants of the original button bar and works fine. The suspect code is in the setInputAreaSelectionStartEnd() function in the TextareaState object.
One last thing I should mention is that, for the time being, I'm trying to keep the control in pure Javascript so I'd like to avoid fixing this with an external library like jQuery if that's possible.
Thanks for your help!
I know what the answer to my own question is.
The sprited buttons are implemented using an HTML list and CSS, where all the list items have a background image. The background image is moved around using CSS to show different buttons and states (like mouseover highlights). Standard CSS button spriting stuff.
This works fine in IE with one exception: IE tries to select the empty list text when you click on the background image "button". The selection in the input textarea goes away and the current selection (which will be returned by document.selection.createRange()) is moved to the empty text in the list item.
The fix for this is simple - I created a variable to cache the selection and a flag. In IE I cache the selection and set the flag in a mousedown event handler. In the text processing, I check for the presence of the flag - if it's set I use the cached range instead of querying document.selection.createRange().
Here are some code snippets:
wmd.ieCachedRange = null;
wmd.ieRetardedClick = false;
if(global.isIE) {
button.onmousedown = function() {
wmd.ieRetardedClick = true;
wmd.ieCachedRange = document.selection.createRange();
};
}
var range;
if(wmd.ieRetardedClick && wmd.ieCachedRange) {
range = wmd.ieCachedRange;
wmd.ieRetardedClick = false;
}
else {
range = doc.selection.createRange();
}
The solution is only a few lines of code and avoids messing around with the DOM and potentially creating layout engine issues.
Thanks for your help, Cristoph. I came up with the answer while thinking and googling about your answer.
You have to blur() a button before IE can select anything else on a page.
Can you provide a minimal example (only containing relevant code) which reproduces the bug?

Categories