I want to do something to all my span elements that have a certain class value.
The something that I will want to do will be based upon an attribute value of the span elements parent.
Can anyone point in the right direction please.
$('span.MYCLASS').each(function() {
switch($(this).parent().attr('THEATTRIBUTE'))
{
case 'something':
// DO SOMETHING
break;
case 'somethingelse':
// DO SOMETHING ELSE
break;
}
});
Change MYCLASS and THEATTRIBUTE to whatever you need them to be. Then you can add in as many case statements as you need.
$("span.spanClass").each(
function(){
$(this).width($(this).parent().width());
}
)
if width is the attribute you want to change..
Also, this page can be very helpful when trying to determine how to select an element or a group of them.
Related
In my application, I have to render Projects, Tasks and Milestones. Projects and Tasks are differently coloured bars, and the Milestone is a Diamond (I'm using BaseRectangle and BaseDiamond respectively).
Since some items in my hierarchy are Projects, Some Tasks and Some Milestones, how can I render differing shapes on each row?
My first thought was to use the common "visible" property, but shapes don't have that, conversely "opacity" makes things invisible, but they still respond to mouse position.
I then tried using an Aggregation factory function, but although my chart renders correctly on first display, it doesn't recalculate the shapes on expanding or collapsing branches.
It seems to me that the factory function should work, but something is breaking in the chart that doesn't throw errors to console.
At the moment in my XML template, I have the following:
rowSettingTemplate has shapes1={path: factory:} and no shapes1 element.
Each of my BaseShapes is in a different fragment which are attached to my TreeTable as dependents.
Example Shape Fragment - Project.fragment.xml
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m" xmlns:gnt2="sap.gantt.simple">
<gnt2:BaseRectangle id="shapeProject"
shapeId="{plandata>id}" countInBirdEye="true"
time="{plandata>start_date}" endTime="{plandata>end_date}"
resizable="true" selectable="true" draggable= "true" connectable="true"
title="{plandata>text}" showTitle="true"
tooltip=""
fill="#0c1" />
</core:FragmentDefinition>
Factory function:
shapeFactory: function(sId, oContext) {
var parentId = (/(.*)-\d+$/.exec(sId))[1];
var rowSettings = sap.ui.getCore().byId(parentId);
var node: Project.Node = oContext.getProperty();
if (String(node.id) == rowSettings.getProperty("rowId")) {
switch (node.type) {
case "project":
return this.byId('shapeProject').clone(sId);
case "task":
return this.byId('shapeTask').clone(sId);
case "milestone":
return this.byId('shapeMilestone').clone(sId);
default:
return this.byId('shapeErr').clone(sId);
}
} else {
return this.byId('shapeEmpty').clone(sId);
}
}
My empty shape is a BaseGroup - note that SAPUI5 crashes if I return a null from factory, so something has to be returned when I actually want nothing.
I also tried wrapping all my shapes in BaseGroup so that the chart always sees the same control type, but that doesn't work. Note also that if I return a clone of Empty each time without any special logic, then the chart works correctly.
I'm hoping that this is a settings or something to ensure that the aggregation works properly each time. My SAPUI5 version is 1.61.2 — I'll try 1.63.1 when I get some time, but I think that this issue is fairly deep down.
If anybody has any ideas or sample code, it would be greatly appreciated.
I have come up with a workaround for this, that may save somebody several hours. Basically instead of defining the shapes1 aggregation via a factory function, I have used the <shapes1> tag instead. My Shapes1 tag contains a reference to my own custom shape which derives from BaseRectangle. My custom shape can then render whatever SVG it requires based on the bound object context. Now my tree can expand and collapse whilst rendering whatever shapes are required.
My renderer now looks like this:
CustomChartShape.prototype.renderElementRectangle = BaseRectangle.prototype.renderElement;
CustomChartShape.prototype.renderElementDiamond = BaseDiamond.prototype.renderElement;
CustomChartShape.prototype.renderElement = function(oRm, oElement) {
// There is possibilities that x is invalid number.
// for instance wrong timestamp binded to time property
if (this.bHasInvalidPropValue) { return; }
var Node = this.getBindingInfo('endTime').binding.getContext().getProperty();
if (Node.type == "milestone") {
this.renderElementDiamond(oRm, oElement);
} else {
this.renderElementRectangle(oRm, oElement);
}
}
I had to provide a 'getD' function that has a fixed width, and I'll have o go through and rewrite several functions, but I think that this will work for me.
As you can see in this plunkr (https://plnkr.co/edit/3EDk5xxSLRolv2t9br84?p=preview) I have two selects: one in the main component behaving as usual, and one in a custom component, inheriting the ngModel settings.
The following code links the innerNgModel to the component ngModel.
ngAfterViewInit() {
//First set the valueAccessor of the outerNgModel
this.ngModel.valueAccessor = this.innerNgModel.valueAccessor;
//Set the innerNgModel to the outerNgModel
//This will copy all properties like validators, change-events etc.
this.innerNgModel = this.ngModel;
}
It works, since the name property is updated by both selects.
However when it first loads the second select has no selection.
I guess I'm missing something, a way to initialize the innerNgModel with the initial value.
This is a weird situation to do something like this, but I believe to get this working they need to implement another life-cycle hook. AfterModelSet or something like that :)
Anyways, you can solve this with a simple setTimeout and a setValue:
ngAfterViewInit() {
this.ngModel.valueAccessor = this.innerNgModel.valueAccessor;
this.innerNgModel = this.ngModel;
setTimeout(() => {
this.innerNgModel.control.setValue(this.ngModel.model);
})
}
plunkr
I need to manipulate the text elements of the first and last tick of an axis to bring them more towards the center.
I am trying to select them, one at the time, with something like svg.select('.tick:last-child text') but it doesn't work. I'd then apply .transform('translate(4,0)')...
Am I doing something wrong? How can I achieve this?
One thing you could do is to create custom sub-selections by adding methods to d3.selection.prototype. You could create a selection.first() method that selects the first item in a selection, and a selection.last() method that selects the last item. For instance:
d3.selection.prototype.first = function() {
return d3.select(this[0][0]);
};
d3.selection.prototype.last = function() {
var last = this.size() - 1;
return d3.select(this[0][last]);
};
This would let you do the following:
var tickLabels = svg.selectAll('.tick text');
tickLabels.first()
.attr('transform','translate(4,0)');
tickLabels.last()
.attr('transform','translate(-4,0)');
Of course, you need to make sure that you only have one axis if you do it that way. Otherwise, specify the axis in your initial selection:
var tickLabels = svg.selectAll('.axis.x .tick text');
HERE is an example.
Here's the cleanest method I've found:
g.selectAll(".tick:first-of-type text").remove();
g.selectAll(".tick:last-of-type text").remove();
As google brought me here, I also want to add a cleaner method to what Adam Grey wrote.
Sometimes you just want to do it without taking a reference of selectAll .
svg.selectAll('.gridlines').filter(function(d, i,list) {
return i === list.length - 1;
}).attr('display', 'none');
the 3rd parameter of the filter function gives you the selected List of elements.
They don't exist in d3 specifically, but you can use the .firstChild and .lastChild methods on a node.
You can first select all of the parents of the node, and then operate within the scope of a .each() method, like so:
d3.selectAll('.myParentElements').each(function(d,i){
var firstChild = this.firstChild,
lastChild = this.lastChild;
//Do stuff with first and last child
});
Within the scope of .each(), this refers to the individual node, which is not wrapped by a d3 selection, so all of the standard methods on a node are available.
Using .filter() with a function also works selection.filter(filter) :
var gridlines;
gridlines = svg.selectAll('.gridlines');
gridlines.filter(function(d, i) {
return i === gridlines.size() - 1;
}).attr('display', 'none');
It's for D3.js v4
d3.selection.prototype.first = function() {
return d3.select(
this.nodes()[0]
);
};
d3.selection.prototype.last = function() {
return d3.select(
this.nodes()[this.size() - 1]
);
};
Example:
var lines = svg.selectAll('line');
lines.first()
.attr('transform','translate(4,0)');
lines.last()
.attr('transform','translate(-4,0)');
Here is another, even though I used Fered's solution for a problem I met.
d3.select(d3.selectAll('*').nodes().reverse()[0])
In Jqgrid, I want to restrict user to select only one check box at any time. When user selects multiple check box only last selected to be in 'selected' state, remaining should be automatically un-selected.
I have set multi select attribute to true. But I am not able to do un-select previously selected item. Is it possible to do if so how?
Thanks
You can use the event beforeSelectRow and reset the selection:
beforeSelectRow: function(rowid, e)
{
jQuery("#list47").jqGrid('resetSelection');
return(true);
}
I've got a fiddle for you so you can check how it works.
You have to do some more stuff:
1. Set multiboxonly to true and multiselect to true
2. Define the events onSelectRow and beforeSelectRow:
3. Define global variable: var lastSel;
The OnSelectRow and beforeSelectRow implementation:
onSelectRow: function (rowId, status, e) {
if (rowId == lastSel) {
$(this).jqGrid("resetSelection");
lastSel = undefined;
status = false;
} else {
lastSel = rowId;
}
},
beforeSelectRow: function (rowId, e) {
$(this).jqGrid("resetSelection");
return true;
}
Having a checkbox in each column implies that you can click more than one at a time. What you are asking for is basically the multiselect: false behavior but with the checkbox column - are you sure you really want the checkboxes in this case?
I know this question is old, but I found a better solution in this Stack Post.
All you have to do is set the following two properties of the jqGrid:
multiselect:true // multi-select checkboxes appear
multiboxonly:true // checkboxes act like radio buttons where only one is selected at a time
I have updated the fiddle made by LeftyX to simply use the multiboxonly setting at this JsFiddle
This was what I needed. It may help someone else.
I'm trying to use the new GWT CellTable widget but my table needs to support one row expansion, i.e. there is a zippy on the left of a row and when it's clicked, the row should expand to provide more detail information and this row should span across all columns. Is it possible to achieve this with the CellTable? How do I add a row that spans all columns between other rows dynamically?
Any help will be appreciated!
GWT 2.5 will add a CellTableBuilder with the exact goal of allowing this kind of things.
You can find a live example at http://showcase2.jlabanca-testing.appspot.com/#!CwCustomDataGrid (click on the "show friends" cells)
Can you not make the additional row invisible using getRowElement(int row) and using DOM methods to set display 'none' when rendered and as blank when the button, to show it, is hit.
I am working on the solution too and my plan for now is to use CSS classes + manual styles manipulation to make it look as I need. Not sure if I be able to merry it with GWT though: http://jsfiddle.net/7WFcF/
I took a different approach to solve this same problem.
The basic concept is using dom elements to add and remove rows based on an event. The following code is an abstract extension of CellTable. You'll want to call this method from your event that gets fired from the click to expand a row.
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
public abstract class ActionCellTable<T> extends CellTable<T> {
protected abstract void addActionsColumn();
Integer previousSelectedRow = null;
public void displayRowDetail(int selectedRow, Element e){
//Get the tbody of the Cell Table
//Assumption that we want the first (only?) tbody.
Element tbody = this.getElement().getElementsByTagName("tbody").getItem(0);
//Get all the trs in the body
NodeList<Element> trs = tbody.getElementsByTagName("tr");
//remove previously selected view, if there was one
if(previousSelectedRow!=null){
trs.getItem(previousSelectedRow+1).removeFromParent();
//If the current is further down the list then the current your index will be one off.
if(selectedRow>previousSelectedRow)selectedRow--;
}
if(previousSelectedRow==null || selectedRow != previousSelectedRow){// if the are equal we don't want to do anything else
Element td = Document.get().createTDElement();
td.setAttribute("colspan", Integer.toString(trs.getItem(selectedRow).getChildNodes().getLength()));
td.appendChild(e);
Element tr = Document.get().createTRElement();
tr.appendChild(td);
tbody.insertAfter(tr, trs.getItem(selectedRow));
previousSelectedRow=selectedRow;
} else {
previousSelectedRow=null;
}
}
}
previousSelectedRow is used to track which item is "expanded", this could probably be achieved using classes or IDs. If needed I can elaborate more on the CellTable, events, views, and activities.