Adding attribute to TinyMCE node with attr not working - wordpress

I'm developing a WordPress plugin that adds a button to TinyMCE, which lets you add an id attribute to the selected element. I have the button displaying, and when it is clicked it runs my function, which I'll call "idFunc" for this demo and it looks like this:
function idFunc() {
// Make sure editor has focus.
editor.focus();
// Get currently selected node
var selectednode = editor.selection.getNode();
// Set the id attribute on the node
selectednode.attr("id","newid");
}
With idFunc() written as above, nothing happens when I click my button. If I change the last line to an alert like this:
function idFunc() {
editor.focus();
var selectednode = editor.selection.getNode();
// Alert with the selected node
alert(selectednode);
}
I get an alert as expected, which says:
The page at mytestingdomain.com says: [object HTMLParagraphElement]
If I have my caret in a div instead of a p element, it says:
The page at mytestingdomain.com says: [object HTMLDivElement]
So I know I'm close, but the attr() function isn't adding any attributes to any elements in the TinyMCE editor.
What am I doing wrong?

The solution to this is easy.
editor.selection.getNode() gives you the common ancestor node (not a jQuery object).
To set the id attribute on the node you may call one of the following commands:
selectednode.setAttribute("id","newid");
or
selectednode.id = "newid";
or using jQuery
$(selectednode).attr("id","newid");

Related

Is it possible to load AppMaker DropDowns with an Option Text and and Value?

I've been able to set the options on an AppMaker DropDown by doing this sort of thing:
google.script.run
.withSuccessHandler(function(oA){app.pages.Notes.descendants.Dropdown1.options=oA;})
.getSelectOptions();//oA is just an array
But I'd like to know how to do load different values in the options and value like we can do it in javascript with something like this:
function updateSelect(vA){
var select = document.getElementById("sel1");
select.options.length = 0;
for(var i=0;i<vA.length;i++)
{
select.options[i] = new Option(vA[i].option,vA[i].value);
}
}
And I tried this by trying to get a hold of the dom element as follows:
var elem=app.pages.myPage.descendants.myDropDown.getElement();
elem.options.length=0;//always gives me an error because options doesn't seem to exist in that object.
So for now I've been using the standard HTML dom elements in an AppMaker Html widget and that works okay as long as your select is on the first page. If it's not on the first page I have found that the onChange event can't load Widgets on pages that are not visible. It is interesting to note however that you can change the contents of HTML widgets even if they are on other non visible pages.
Anyway the simple question is how can one load one thing into value and another thing into option text in an AppMaker DropDown Widget?
<option value="value">text</option>
If you have a predefined array for your options and values you could do the following for your onAttach Event of your dropdown:
var options = ['one thing','two thing','three thing'];
var names = ['another one thing','another two thing','another three thing'];
widget.options = options;
widget.names = names;
In this case the values that would get recorded would be the options array, but the items that would be displayed would be from the names array. Hope this gets you on the right path.

Override default style behavior of TinyMCE on new element

I was trying to search for a way to override default behavior of TinyMCE when it applies same styles to new elements. For example, when we apply some style to a paragraph and hit enter for new paragraph, it inherits same styles. Is it possible to override this behavior?
Yes, it is.
You will have to register the keyup event and check for the ENTER key.
Then you check the actual node the caret is in and you may add/remove classes or whatever. Use the setup tinymce configuration parameter to add the handler:
setup:function(ed){
ed.on("keyup", function(e){
if(e.keyCode == 13){ // ENTER
var node = ed.selection.getNode();
// do your magic here
}
});
}

Reactively add class after Session changes

I have a Session named dropdownVisible.
Session.setDefault('dropdownVisible', false)
I have the following template / event
template(name="authUser")
a(id="user-link") User Link
if dropdownVisible
.dropdown-container
p This is a dropdown
Template.authUser.events
'click #user-link': ->
if Session.equals('dropdownVisible',false)
Session.set('dropdownVisible', true)
else
Session.closeDropdown()
Whenever I click on #user-link the dropdown will toggle open/close. This works fine.
Now I am trying to add an extra class to the dropdown container whenever it's rendered.
So I have
Template.loggedOut.rendered = ->
$('.dropdown-container').addClass("test")
This adds the class the first time when it's rendered, but not after that. I suspect it has something to do with reactivity. I tried wrapping it in a Tracker.autorun function but that doesn't work. How can I have the addClass be invoked every time my dropdown opens.
** EDIT
I used the addClass example, but in actually I want to animate the dropdown using _uihooks. I just used the addClass example to make the example simpler as it is probably a similar issue to that I'm facing with the uihooks.
Template.loggedOut.rendered = ->
#find('.parent-of-dropdown-container')._uihooks =
insertElement: (node, next) ->
$(node).addClass("animate").insertBefore(next)
Seems to me that this should do it, no?
Template.authUser.events
'click #user-link': ->
if Session.equals('dropdownVisible',false)
Session.set('dropdownVisible', true)
$('.dropdown-container').addClass("test")
else
Session.closeDropdown()
Ok I found the problem.
The 'next' argument as defined in the insertElement function is the DOM element positioned right after the inserted element ('node'). In this example, there was none, as 'node' (.dropdown-container) was the only element inside the wrapping container. Hence it never got inserted.

Anguilla - Updating a field's value from a popup?

I have a modal popup that appears whenever an editor tries to save a component with some values (a date field in the past in this case).
In this popup I show the editor a few options (very similar to the default "Open Shared Item" dialog) and an OK/Cancel button combo. On Cancel I fire the "cancel" event and the editor goes back to the editing screen, all good here. On "OK" I want to change the value of the field to match whatever the editor selected, then save.
I tried to use an approach with FieldBuilder and the sample Boris mentioned on this other topic but I can't get to the field from my popup dialog.
Any suggestions on how I can go and modify the xml of the item (could be also a page) from a modal popup?
EDIT: Code used in getControlForFieldName
function getControlForFieldName(name) {
var fieldBuilder = $display.getView().properties.controls.fieldBuilder;
var fieldsContainer = fieldBuilder.properties.input;
var fieldsNode = fieldsContainer.getElement();
var fieldContainer = $dom.getFirstElementChild(fieldsNode);
while (fieldContainer) {
var labelNode = $dom.getFirstElementChild(fieldContainer);
var fieldNode = $dom.getNextElementSibling(labelNode);
var control = fieldNode.control;
if (control.getFieldName() == name) {
return control;
}
fieldContainer = $dom.getNextElementSibling(fieldContainer);
}
}
EDIT #2
After Frank's advice, and some help from Jaime & Frank offline, I got it to work as follows:
The popup is called from a Command Extension (Save & Close in my case)
The command.js specifies an event handler that gets called on "submit" (== OK was pressed)
$evt.addEventHandler(p.dialogPopup, "submit",
this.getDelegate(this._onPopupSubmit));
In my popup I am passing the selected item (it's a keyword ID) to the event handler:
this.fireEvent("submit", { id: select.options[select.selectedIndex].value });
and now back in the event handler _onPopupSubmit(e) I just read e.data.id, load this keyword, get properties like ID & Title, and update the metadata of the item using item.setMetadata("new metadata with updated values").
Simple :)
Your code runs in a popup, so any references you make to global variables will be taken from the popup window.
So when you get the fieldBuilder:
var fieldBuilder = $display.getView().properties.controls.fieldBuilder;
$display is a reference to a global variable. So this actually looks for the FieldBuilder in the popup window (which doesn't have one).
To get the FieldBuilder of the Component window, you can get it from the opener:
var fieldBuilder = opener.$display.getView().properties.controls.fieldBuilder;
You might want to consider actually passing the updated value to either a callback function or with a (custom) event though, since that makes your popup less dependent on opener. trick.

How can I get value from radio-button inserted into innerHtml

I have sort of a table with a radio-button column. I managed to make radio-button column work dynamically inserting into a cell (div if matter). But, on postback innerHtml hasn't been updated with "checked" attribute.
Could you give me an idea how can I find out (on the server) if radio-button has been checked?
More info: This is on user control inside update panel.
This would be good post on my topic, still doesn't help
Any reason you cannot use a standard asp:RadioButton and use javascript to ensure it is mutually exclusive. I have done this before by adding a custom attribute to the radiobutton and then using a js function to uncheck all items with that attribute and then check the selected one. This works around the IE issue which prevents the groupname attribute from working on radioboxes that are in different containers.
radioButton.InputAttributes.Add("ClientGroupName", "grpRadioList");
radioButton.InputAttributes.Add("onclick",
string.Format(
"javascript:radiobuttonToggle('{0}','ClientGroupName','grpRadioList');"
,radioButton.ClientID));
and use the following JS to uncheck all radios and then check the one you want.
Note i used InputAttributes instead of Attributes as the radiobutton is wrapped inside a span tag so InputAttributes is for items added to the actual input control rather than the span.
function radiobuttonToggle(selectedRB, attribName, attribValue)
{
var objRadio = document.getElementById(selectedRB);
for(i = 0; i < document.forms[0].elements.length; i++)
{
elm = document.forms[0].elements[i];
if (elm.type == 'radio')
{
if(elm.getAttribute(attribName) == attribValue)
elm.checked = false;
}
}
objRadio.checked = true;
}
You can then expose radioButton.Checked as a property in your CS file and reuse this as a control.
Check Form.Request("radio-name") != null
You only get a non-null value when it's been checked.
Make sure your page elements are being rebuilt correctly on postback. Any binding process that inserted the radio buttons the first time around will have to be re-run before you can access them the second time.
Here is a working example, first I add radios to my webform by the method you linked :
function addRadio()
{
try{
rdo = document.createElement('<input type="radio" name="fldID" />');
}catch(err){
rdo = document.createElement('input');
}
rdo.setAttribute('type','radio');
rdo.setAttribute('name','fldID');
document.getElementById('container').appendChild(rdo);
}
Then at code behind I used only the code below to get the radio's value :
string value = Request["fldID"];
So, be sure you're trying to get the name of the radio buttons at server side. You should use name attribute at server side, not id.

Resources