I would like to know how to retrieve text (IText / Text) value from text object?
var textObj = new fabric.IText('hello friends', { left: 100, top: 100 });
canvas.add(textObj);
So how I can retrieve the text value of 'textObj'?
textObj.text or textObj.get('text') works on Fabricjs 2.x
To get the text from the selected object
const obj = canvas.getActiveObject()
if (obj && obj.isType('textbox')) {
const { text } = obj
// ...
}
Related
I am using autoColumns: true and data loaded through the builtin ajax call ajaxURL: "/...". After data is loaded I would like to dynamically update a few columns to allow dropdowns to be used. I know I could pre-define the column definitions prior to loading data but I am trying to do this dynamically.
In the code example below, I am adding new columns after data is loaded dynamically through a razor loop. This builds select lists dynamically and I used it as a POC to test part of what I need to do with updating column definitions.
How do I replace an existing columns definition and trigger an update without replacing the cells below data?
After the column definition is updated while keeping data how do I make sure the editor "select" is set to the cell value, my thinking this would happen automatically after the definition is updated.
Thanks!
dataLoaded: function(data) {
/////////////////////////////////////////
// Example, adding dynamic columns
/////////////////////////////////////////
#foreach(var item in Model.Report.ReportFields) {
<text>
table.addColumn({
title: "#item.FieldName",
field: "#item.FieldName",
editor: "select",
editorParams: {
values: {
#foreach(var fi in item.ReportFieldItems) {
<text> "#fi.ItemValue": "#fi.ItemName", </text>
}
}
}
});
</text>
}
///////////////////////////////////////////////////////////////
// Example updating column definition for field name "Status"
///////////////////////////////////////////////////////////////
var aColumns = table.getColumns();
for (var i = 0; i < aColumns.length; i++) {
if (aColumns[i]._column.field == 'Status') {
console.log(aColumns[i]._column.defitions);
aColumns[i]._column.definition.editor = "select";
var obj = {
key1: "value1",
key2: "value2"
};
var obj2 = {
values: obj
};
aColumns[i]._column.definition.editorParams = obj2;
}
}
}
table.setColumns is my friend. Before I could use this I needed to build the column definition from the returned column data. Seems like an opportunity for a new feature instead of a quick loop to do this directly. This answers both questions, first to update an existing definition and to not replace the existing data.
var newColumns = [];
var aColumns = table.getColumns();
for (var i = 0; i < aColumns.length; i++) {
if (aColumns[i]._column.field == 'Status') {
console.log(aColumns[i]._column.defitions);
aColumns[i]._column.definition.editor = "select";
var obj = {
key1: "value1",
key2: "value2"
};
var obj2 = {
values: obj
};
aColumns[i]._column.definition.editorParams = obj2;
}
newColumns.push(aColumns[i]._column.definition);
}
console.log(newColumns);
table.setColumns(newColumns);
How to use an icon which is not provided by WinJS? For example, use one from here.
The html looks like:
<div data-win-control="WinJS.UI.SplitViewCommand" data-win-options="{ label: 'Home', icon: 'home'}"></div>
The png image should be 20x20 pixels with a transparent background (https://msdn.microsoft.com/en-us/library/windows/apps/hh700483.aspx). The png is set as in javascript:
document.getElementById("thatFancyButton").style.backgroundImage = url('pathOfPNGImage');
so in your case it is (notice \' \' in url()):
<div data-win-control="WinJS.UI.SplitViewCommand" data-win-options="{ label: 'Home', icon: 'url(\'pathOfPng.png\')'}"></div>
You can also set one letter glyphs like icon: '©' and it will show it as icon.
Below is the snippet of the SplitViewCommand icon setting logic:
/// <field type="String" locid="WinJS.UI.SplitViewCommand.icon" helpKeyword="WinJS.UI.SplitViewCommand.icon">
/// Gets or sets the icon of the SplitViewCommand. This value is either one of the values of the AppBarIcon enumeration or the path of a custom PNG file.
/// </field>
icon: {
get: function () {
return this._icon;
},
set: function (value) {
this._icon = (_Icon[value] || value);
// If the icon's a single character, presume a glyph
if (this._icon && this._icon.length === 1) {
// Set the glyph
this._imageSpan.textContent = this._icon;
this._imageSpan.style.backgroundImage = "";
this._imageSpan.style.msHighContrastAdjust = "";
this._imageSpan.style.display = "";
} else if (this._icon && this._icon.length > 1) {
// Must be an image, set that
this._imageSpan.textContent = "";
this._imageSpan.style.backgroundImage = this._icon;
this._imageSpan.style.msHighContrastAdjust = "none";
this._imageSpan.style.display = "";
} else {
this._imageSpan.textContent = "";
this._imageSpan.style.backgroundImage = "";
this._imageSpan.style.msHighContrastAdjust = "";
this._imageSpan.style.display = "none";
}
}
},
If you happen to have errors with the background image size, modify win-commandimage class. I did this fix in styles to fit the image into button correctly:
.win-commandimage {
background-size:contain;
}
I want to remove elements based on ID with double click
Tried this but it is not working:
paper.on('cell:pointerdblclick', function (cellView,cell)
{
selectedId = cellView.model.id;
selected = cellView.model;
$.each(cellsAdded, function(index, value)
{
if(selectedId !== cellsAdded[index])
{
selected.remove();
}
});
});
These are the cells in the graph:
var cellsAdded = graph.addCells([sidebar, rect, circle1, circle2, circle3, rectGroup0, diamond]);
All of the above cells have ids and I dont want to remove them, I only want to remove other elements which are not part of the above
I have a geojson file which I'm getting from this website which somehow contains corrupt data, with a coordinate value = null.
http://measuringamsterdam.nl/datalist/kijk/
And I'm using it in my code like this:
//Retrieve all data and add to map
$.each(datalistObject['idlist'], function(key, value) {
$.getJSON('http://measuringamsterdam.nl/datalist/kijk/' + value['id'], function(data) {
textbox = value['name'];
var dataid = L.geoJson([data], {
style: function (feature) {
return feature.properties && feature.properties.style;
},
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {
icon: value['icon']
});
}
}).addTo(jsonGroup);
console.log(jsonGroup);
},function(xhr) { console.error(xhr); });
});
Now somehow I need to filter out the features/objects where the coordinates have a null value.
I really need to filter the data that point in my code since I need the + value['id'] part in the getJSON code.
Ane ideas?
Using the following code you will generate a new array. Which will include only the filtered data.
var newArray = data.filter(function (el) {
return el.value != 'null';
});
You can also apply multiple filters, for example:
return el.value_a != 'null' && el.value_b > 100;
Hopefully this will work!
Using sharepoint build in lookup column and it set to required field. SharePoint automatically selects the first item in the dropdown box (kinda misleading for the end users).
Is there a way to display blank or Null for the first row of this drop down box?
(I am open to any solution. I prefer javascript type solution)
For Choice fields, the default value is configured in the column settings. If the "Default value" input box is populated, delete the value in order to use no default value.
Edit
For Lookup fields, the field seems to change dramatically if it is required. Fields that are NOT required have a "(None)" value by default. However, toggling the field to required will remove the "(None)" value and the first value is selected automatically.
One thing I found, is that if you use JavaScript to add the null value to the dropdown and then try to press OK you get an error page: "An unexpected error has occurred." As a workaround, I wrote some more code to do a quick validation that the field has a value before the form is submitted. If the field has no value, then it will prompt the user and cancel the submit. (Note: this code is only attached to the OK buttons so you may get errors while editing EditForm.aspx.. just choose a value for your lookup field and you'll be able to edit like normal)
Anyways, onto the code... I think the only line you'll need to change is var fieldTitle = 'Large Lookup Field'; to update it to the name of your field.
<script type="text/javascript">
function GetDropdownByTitle(title) {
var dropdowns = document.getElementsByTagName('select');
for (var i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].title === title) {
return dropdowns[i];
}
}
return null;
}
function GetOKButtons() {
var inputs = document.getElementsByTagName('input');
var len = inputs.length;
var okButtons = [];
for (var i = 0; i < len; i++) {
if (inputs[i].type && inputs[i].type.toLowerCase() === 'button' &&
inputs[i].id && inputs[i].id.indexOf('diidIOSaveItem') >= 0) {
okButtons.push(inputs[i]);
}
}
return okButtons;
}
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value',value);
if (typeof(optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option,options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
oDropdown.options.selectedIndex = 0;
}
function WrapClickEvent(element, newFunction) {
var clickFunc = element.onclick;
element.onclick = function(event){
if (newFunction()) {
clickFunc();
}
};
}
function MyCustomExecuteFunction() {
// find the dropdown
var fieldTitle = 'Large Lookup Field';
var dropdown = GetDropdownByTitle(fieldTitle);
if (null === dropdown) {
alert('Unable to get dropdown');
return;
}
AddValueToDropdown(dropdown, '', '', 0);
// add a custom validate function to the page
var funcValidate = function() {
if (0 === dropdown.selectedIndex) {
alert("Please choose a value for " + fieldTitle + ".");
// require a selection other than the first item (our blank value)
return false;
}
return true;
};
var okButtons = GetOKButtons();
for (var b = 0; b < okButtons.length; b++) {
WrapClickEvent(okButtons[b], funcValidate);
}
}
_spBodyOnLoadFunctionNames.push("MyCustomExecuteFunction");
</script>
In response Kit Menke, I've made a few changes to the code so it will persist previous value of the dropdown. I have added the following lines of code to AddValueToDropdown()....
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var selectedIndex
if (oDropdown.options.selectedIndex)
selectedIndex = oDropdown.options.selectedIndex;
else
selectedIndex = -1;
// original code goes here
// changed last line of code (added "selectedIndex+1")
oDropdown.options.selectedIndex = selectedIndex+1;
}
To improve on top of Aaronster's answer: AddValueToDropdown can be done that way:
var injectedBlankValue = false;
function AddValueToDropdown(oDropdown, text, value, optionnumber) {
for (i = 0; i < oDropdown.options.length; i++) {
option = oDropdown.options[i];
if(option.getAttribute('selected')) // If one is already explicitely selected: we skip the whole process
return;
}
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value', value);
if (typeof (optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option, options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
// changed last line of code (added 'selectedIndex+1')
oDropdown.options.selectedIndex = 0;
injectedBlankValue = true;
}
This is needed for document libraries where "add" and "set properties" are two distinct pages.
And funcValidate starts with:
var funcValidate = function () {
if (!injectedBlankValue)
return true;
All these changes is to make the whole thing work with document libraries.