In my Office add-in I have a checkbox like the following:
<div class="ms-CheckBox">
<input id="inputId" type="checkbox" class="ms-CheckBox-input" />
<label id="labelId" role="checkbox" class="ms-CheckBox-field" aria-checked="false" name="checkboxA" for="inputId>
<span class="ms-Label">Text</span>
</label>
</div>
I want to retrieve through JavaScript its checked status (or its aria-ckecked status, I'm still not getting the differences between them), which I thought was through document.getElementById( 'labelId' ).checked, since it's specified in the documentation that they have an optional checked member, but I only get an undefined with it.
I'm very new to these technologies and have a couple concerns:
Does "optional member" mean that I have to explicitly create it so that it exists? If so, how can I do that?
However the checked member may come to existance, do I have to manually handle its value every time it's clicked on by the user or is it already internally managed and I simply haven't found the way to access it yet?
Maybe I just can't see a mistake I've made on the html code for the checkbox?
Thank you in advance!
You have several sources of documentation on Office UI Fabric depend on framework you are using or about to use. Your choices are:
JavaScript only (no framework)
React
Angular
Form the look up table you would choose JavaScript only link and follow it to find the component you are interested in. Before that I would suggest to read "Get Started using Fabric JS".
Now when you have documentation on checkbox component of vanilla JS implementation, follow the steps to set up your checkbox. This would include:
Confirm that you have references to Fabric's CSS and JavaScript on your page
Copy the HTML from one of the samples below into your page.
<div class="ms-CheckBox">
<input tabindex="-1" type="checkbox" class="ms-CheckBox-input">
<label role="checkbox" class="ms-CheckBox-field" tabindex="0" aria-checked="false" name="checkboxa">
<span class="ms-Label">Checkbox</span>
</label>
</div>
Add the following tag to your page, below the references to Fabric's JS, to instantiate all CheckBox components on the page.
<script type="text/javascript">
var CheckBoxElements = document.querySelectorAll(".ms-CheckBox");
for (var i = 0; i < CheckBoxElements.length; i++) {
new fabric['CheckBox'](CheckBoxElements[i]);
}
</script>
To get the status of your checkbox use method getValue() which returns true or false whether the component is checked or not.
Related
I have a <h:selectOneMenu>. Depending on what is selected will be shown one of the many <div>s related to the selection and will be hidden the others.
Each <div> has some <h:inputText> that write to different #ViewScoped beans. Some of this <div>s even write to the same properties in the beans.
Ex.
<div>
<h:outputLabel for="list" value="Items"/>
<div>
<h:message for="list"/>
<h:selectOneMenu id="list" value="#{bean.selectedItem}" >
<f:selectItem itemLabel="Select one"></f:selectItem>
<f:selectItems value="bean.someItemsList" />
</h:selectOneMenu>
</div>
</div>
<div id="item1">
<!-- some other input fields -->
<div>
<h:message for="item1input1"/>
<h:inputText id="item3input1" value="bean.thisIsTheSameProperty" />
</div>
</div>
<div id="item2">
<!-- some other input fields -->
</div>
<div id="item3">
<!-- some other input fields -->
<div>
<h:message for="item3input1"/>
<h:inputText id="item3input1" value="bean.thisIsTheSameProperty" />
</div>
</div>
The problem: When I select an item that will display a <div> (ex. <div id="item1">) and there is also another hidden <div> (ex. <div id="item3">) that writes to the same bean properties (ex. value="bean.thisIsTheSameProperty") and this properties are annotated with javax.validation.constraints.#NotNull, even I give a value to this input fields, when I submit the form, I think JSF runs also the hidden <div> (which normally has no input set).
What I see during debugging: When the form will be submited I see the setter of the bean will be called twice. The first time the bean properties will be set with the correct valeus I typed in but the second time the setter will be called with null values. So the validation will fail because of the #NotNull.
My assumption is that JSF tries to set the bean values twice, one for the input fields on the shown <div> and the second time for the hidden <div> (because they point to the same bean properties), but for the hidden bean there are not input fields set (they are null).
I show/hide the <div>s with jQuery depending on the item selected from the <h:selectOneMenu>.
Ex.
$('#item1').show();
$('#item1').hide();
$('#item2').show();
$('#item2').hide();
$('#item3').show();
$('#item3').hide();
Is there a way to say JSF to not consider the hidden <div>s at all?
You seem to be assuming that hidden inputs (hidden via CSS) are not submitted to the server. This assumption is wrong and it is a plain html thing btw, not JSF related at all.
See e.g. Stop an input field in a form from being submitted
But still, it would allow client-side manipulation via a browser developer tool to 'attack' you application. JSF, contrary to all the hyped javascript UI frameworks is a full grown 'MVC framework' that has build in protection against client-side manipulation/tampering and CSRF, XSS for which you'd need OWASP related functionality in other framework. (That and other things makes JSF (with PrimeFaces, OmniFaces and DeltaSpike) for me still a great framework to quickly develop business oriented applications.)
You'd better use ajax to conditionally render one div or the other but you cannot 'update' the divs when they are defined like you have them.
See also:
Ajax update/render does not work on a component which has rendered attribute
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
The answer from #Kukeltje and comment from #drkunibar worked for me.
I modified it a little.
Actual solution:
$('#myForm').submit(function() {
if($('#list').find(':selected').val() === 'itemOption1') {
$('item3').remove();
} else if($('#list').find(':selected').val() === 'itemOption3') {
$('item1').remove();
}
});
I check to see which option is selected. If option1 is selected then I remove the div with iditem3 from the DOM, or else if the option3 is selected then I remove the div with iditem1 from the DOM.
In this way the binding bean.thisIsTheSameProperty is transmitted only one and the values will not be overriden.
Thank you.
I have a Domain Class Project with a one-to-many property users :
static hasMany = [users: User]
In my scaffolding code the view is created with:
<div class="fieldcontain ${hasErrors(bean: projectInstance, field: 'users', 'error')} ">
<label for="users">
<g:message code="project.users.label" default="Users" />
</label>
<g:select name="users" from="${usermanagement.User.list()}" multiple="multiple" optionKey="id" size="5" value="${projectInstance?.users*.id}" class="many-to-many"/>
</div>
This results in a simple list where I can select multiple users. The user list is expected to be quite big so this selection isn't really viable. Is there a simple way in grails to do this a bit more comfortable? The best solution I can imagine would be a list with an autocomplete searchform and a second list where the selected entries are displayed.
I don't think that there is an easy way to do this and that I probably have to use javascript or jquery (autocomplete etc.)
Any help improving my current status (selection from huge list via ctrl + click)
would be very appreciated.
There is a jQuery plugin called Chosen that will do what you are wanting, it supports multiple selections. I have a use case much like yours in one of my apps and Chosen worked out great:
http://harvesthq.github.io/chosen/
A possible solution is using some javascript based stuff like boostrap select2 or Kendo UI Multiselect. They are based on a html select box that unobtrusively enhanced the selection model of a this html element. So there is no real javascript code to implement, since the selection model for the html form stays the same as with disabled javascript.
To get an idea of the setup I’m using in my application I set up this simplified example:
<div ng-controller="Ctrl">
<ul>
<li ng-repeat="oConfigEntry in oConfiguration.oConfigEntriesColl">
<ul>{{oConfigEntry.sDescription}}
<li ng-repeat="oConfigSubEntry in oConfigEntry.oConfigSubEntriesColl">{{oConfigSubEntry.sDescription}}
<input type='checkbox' ng-model='oConfigSubEntry.bNoOption' />{{oConfigSubEntry.bNoOption}}
<ul>
<li ng-repeat='oConfigSubSubEntry in oConfigSubEntry.oConfigSubSubEntriesColl'>{{oConfigSubSubEntry.sDescription}}
<input type='number' placeholder='length' ng-model='oConfigSubSubEntry.dLength' />
<input type='number' placeholder='width' ng-model='oConfigSubSubEntry.dWidth' />
<input type='number' placeholder='height' ng-model='oConfigSubSubEntry.dHeight' />
<input type='checkbox' title='opt1' ng-model='oConfigSubSubEntry.bOpt1' />
<input type='checkbox' title='opt2' ng-model='oConfigSubSubEntry.bOpt2' />
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre ng-bind="oConfiguration | json"></pre>
</div>
see http://jsfiddle.net/ppellegr/4QABQ/
Unfortunately the problem I’m facing in the real application cannot be reproduced in the latter mentioned example.
The problem is that in the real application the checkboxes are not clickable. Clicking the checkboxes do not check them. The checkboxes remain unchecked.
The other way around If the corresponding model is initialized the checkboxes are checked but cannot be unchecked by clicking them.
Even plain checkboxes with no model assigned cannot be checked if they are placed within a nested ng-repeat.
e.g.
<input type="checkbox" />
Has anyone already noticed such a phenomenon?
additional observations:
The first click on the checkbox changes the value of the model.
Subsequent clicks do not change the value. The value of the model remains the
same.
While the first click on the checkbox changes the value of the
model, the checkbox itself remains checked/unchecked depending on the
inital value of the model.
My guess is that another element is positioned in such a way as to cover or overlap the checkbox, and that is preventing you from interacting with it. Assuming you have no inline styles applied to your markup, you can test this easily by disabling CSS in your browser (you may need to install an extension to do this, eg: How to disable CSS in Browser for testing purposes).
If you find that you can click the checkbox like that, you then need to debug your css to find the offending element. Use firebug or chrome developer tools to explore the markup and css.
In the real application the checkbox showing the described behavior is within a list that is enriched by a little jQuery feature making the list collapsible and expandable...
function prepareList() {
$('#ConfigContainer').find('li:has(ul)')
.click(function (event) {
if (this == event.target) {
$(this).toggleClass('expanded');
$(this).children('ul').toggle('medium');
}
return false;
})
.addClass('collapsed')
.children('ul').hide();
}
$(document).ready(function () {
prepareList();
});
see http://jsfiddle.net/ppellegr/cP726/
In this example the described behavior can be reproduced...
The culprit line of code is obvious:
return false;
This stops propagation of event and obviously interferes with the checkbox...
Lesson learnt:
check whether javascript, jQuery or the like are interfering with angularjs...
consider writing an angular directive...
<div class="xCoord">
<label for="xCoordInput">X:</label>
<input value="" name="x" id="xCoordInput" class="text coordinates x ">
</div>
What I would like to do is to change this value (xCoordInput) on someone else website? This is a game and I don't know how I would change their website from my own website.
I like to autofill forms with a bookmarklet. I use them at work to fill out tedious forms when I am testing webpages. To build one create a bookmark and edit the url value of the bookmark to hold a javascript function object like this one.
javascript:(function(){
var xCoord = document.getElementsByClassName("xCoord")[0];
xCoord.getElementsByTagName("input")[0].value="whatever";
})();
Nothing about doing this in principle is wrong or illegal unless you are using it to cheat or break the law.
Is there a specific reason that most everyone implements edit-in-place as a shown 'display' div and a hidden 'edit' div that are toggled on and off when somebody clicks on the associated 'edit' button like so?
<div id="title">
<div class="display">
<h1>
My Title
</h1>
</div>
<div class="edit">
<input type="text" value="My Title" />
<span class="save_edit_button"></span>
Cancel
</div>
</div>
Everywhere I look, I see edit-in-place basically handled like this. This approach certainly makes sense when you are rendering all views on the server side and delivering them to the client. However, with pure AJAX apps and frameworks like backbone.js, it seems that we could make our code much more DRY by rendering edit-in-place form elements on the fly as necessary, possibly even making a factory method that determines which form element to render. e.g.
an H1 element with class "title" is replaced by <input type="text" />
a span with class "year_founded" is replaced by <input type="number" min="1900" max="2050" />
a span with class "price" is replaced by an input with the appropriate mask to only allow prices to be input.
Is this practice of rendering all edit-in-place form elements a historical legacy leftover from when pages were rendered on the server-side?
Given the flexibility and power we have with client-side MVC frameworks like Backbone.js, is there a reason for not creating and inserting the form elements on the fly when necessary using a factory method? Something like this:
HTML
<div id="description">
Lorem ipsum dolar set amit...
</div>
<span class="edit_button"></span>
Backbone.js View
events: {
"click .edit_button": "renderEditInPlaceForm",
},
renderEditInPlaceForm: function:(e) {
var el = $(e.currentTarget).previous();
var id = el.attr('id');
var value = el.text();
var tagName = el.tagName();
var view = new editInPlaceForm({
id: id,
type: tagName,
value: value
});
$("#id").html(view.render().el)
},
Where editInPlaceForm is a factory that returns the appropriate edit-in-place form element type based on tagName. This factory view also controls all its own logic for saving an edit, canceling an edit, making requests to the server and rerendering the appropriate original element that was replaced with the .html() function?
It seems to me that if we use this approach then we could also render the <span class="edit_button"></span> buttons on the fly based on a user's editing rights like so:
<h1 id="title">
<%= document.get("title") %>
</h1>
<% if (user.allowedToEdit( document, title )) { %>
<span class="edit_glyph"></span>
<% } %>
where the allowedToEdit function on the user model accepts a model and attribute as its arguments.
It's an interesting idea. The devil is in the detail.
While your simple example is easily rendered as an editable form on the fly, things quickly get trickier when dealing with other data types.
For example - suppose my edit form requires the user to choose a value from a select list. On the display form I can simply display the user's choice, but for the edit form I am going to need those other available choices. Where do I hide them on the display? Similar issues exist for checkboxes, radio lists...
So, perhaps we should consider rendering the edit form, and then deriving our display-view from that?
After 5 Backbone apps I came to same thoughts.
When things are complicated you have forms to show relations between user data,
but in simple cases you just need input, select, checkbox over h1, div or span
Now I am searching for jQuery plugin to make simple in place editing without ajax.
jQuery but not Backbone becuase I don't want to be tight coupled with Backbone for such small thing.
Likely to wright my own jQuery + Synapse plugin http://bruth.github.com/synapse/docs/.
Synapse for binding with model and jQuery for input placing