So my javascript is bad, but I have a datatables need that I cannot figure out. Relevant code here:
$('#lesson-table').DataTable( {
'data': cleanData,
'paging': false,
'order': [[ 8, 'asc' ], [ 3, 'desc' ], [ 1, 'desc' ]],
initComplete: function () {
// this is where we populate the filter dropdowns
this.api().columns([0,1,2,6,7]).every( function () {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.header()) )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
var val = $('<div/>').html(d).text();
select.append( '<option value="' + val + '">' + val + '</option>' );
} );
} );
}
} );
// this removes duplicate dropdown values
var usedNames = {};
$("#lesson-table select > option").each(function () {
if (usedNames[this.value]) {
$(this).remove();
} else {
usedNames[this.value] = this.text;
}
});
So the change that was made in my datasource is that columns 1, the second column in the set, is now a comma separated list of items. Most of the time it is one item say: "Entertainment", but sometimes it can be "Entertainment, Sports, Healthcare" At the moment, it will show that list as an option in my dropdown, but what I need it to do is split them up and then filter by contains...not by exact.
Hope that makes sense. Can explain more if needed.
Which app_id should be used for importing into a contact column? Also, what should the mappings parameter look like?
podio.ImporterService.ImportAppItems(fileId, appId, new List<ImportMappingField> {
new ImportMappingField { FieldId = primaryFieldId, Unique = false, Value = new { column_id = "0" }},
new ImportMappingField { FieldId = contactfieldId, Unique = false, Value = new { column_id = "1", app_id = ???, mappings = new []{ ??? }}}
})
Edit:
I figured it out. Below is an example that works for me.
podio.ImporterService.ImportAppItems(373063497, 18803129, new List<ImportMappingField> {
new ImportMappingField {
FieldId = 148580608,
Unique = false,
Value = new { column_id = "0" }
},
new ImportMappingField {
FieldId = 148580614,
Unique = false,
Value = new {
mappings = new []{
new {
field_key = "mail",
unique = "true",
column_id = "4"
}
}
}
}
});
See the API documentation [1]
[1] https://developers.podio.com/doc/contacts
I'm new to Dojo and I'm making my first widget to be used in EPiServer CMS.
The widget is supposed to dynamically add contacts when clicking on a button. This means that the only control my templateString has is a button. When clicking on it I call a function that creates all of the other controls that will contain the contact infomation, such as name, email etc. This is working fine, I use domConstruct.create without a problem.
Thing is, when I want to create the existing contacts based on the value that comes from the server I can't manage to use domConstruct.create, it just returns "undefined". I'm making the call in the postCreate event which happens after the DOM is ready. (I've tested this as well). Does anyone have a clue what could be wrong? Like I said creating the controls when clicking on the Add button works like a charm.
The function that throws the error is:
postCreate: function () {
// call base implementation
this.inherited(arguments);
//this._loadContacts(this.value);
var node = domConstruct.create("fieldset", { id: "test" }, "cccp"); //this simple create instruction returns undefined here.
//Bind button
this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));
},
Exactly on the line that does the domConstruct.create. Below is the entire code for the widget:
define([
"dojo/_base/array",
"dojo/_base/connect",
"dojo/_base/declare",
"dojo/_base/lang",
"dojo/dom-construct",
"dojo/on",
"dijit/_CssStateMixin",
"dijit/_Widget",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"epi/epi",
"epi/shell/widget/_ValueRequiredMixin"
],
function (
array,
connect,
declare,
lang,
domConstruct,
on,
_CssStateMixin,
_Widget,
_TemplatedMixin,
_WidgetsInTemplateMixin,
epi,
_ValueRequiredMixin
) {
var amountContacts = 0;
var contactContainerPrefixName = "contactInfo";
return declare("meridian.editors.StringList", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _CssStateMixin, _ValueRequiredMixin], {
templateString: "<div class=\"dijitInline\">\
<form id=\"cccp\" action=\"\">\
</form>\
<button id=\"btnAdd\" data-dojo-attach-point=\"btnAdd\" type=\"button\" class=\"\">Add Contact</button><br/> \
<span>${helptext}</span>\
</div>",
baseClass: "epiStringList",
helptext: "Place items on separate lines",
intermediateChanges: false,
value: null,
multiple: true,
onChange: function (value) { },
_onChange: function (value) {
this.onChange(value);
},
postCreate: function () {
// call base implementation
this.inherited(arguments);
//this._loadContacts(this.value);
var node = domConstruct.create("fieldset", { id: "test" }, "cccp"); //this simple create instruction returns undefined here.
//Bind button
this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));
},
isValid: function () {
// summary:
// Check if widget's value is valid.
// tags:
// protected, override
return !this.required || lang.isArray(this.value) && this.value.length > 0 && this.value.join() != "";
},
_loadContacts:function(data)
{
for (var i = 0; i < data.length; i++) {
this._createContact(data[i]);
}
},
_createContact:function(data)
{
//increase the number of contacts
amountContacts++;
var contactInfoContainer = contactContainerPrefixName+amountContacts;
//Create container for contact data
var contactInfo = domConstruct.create("fieldset", { id: contactInfoContainer }, "cccp");
//Create container for PROPERTIES
var contactInfoProperties = domConstruct.create("div", {class: "properties"}, contactInfoContainer);
//Name
this._createTextbox("name", data.fullName, "Name", contactInfoProperties, false, false);
/*//Email
this._createTextbox("email", "Email", contactInfoProperties, false);
//Phone 1
this._createTextbox("phoneOne", "Phone 1", contactInfoProperties, true);
//Phone 2
this._createTextbox("phoneTwo", "Phone 2", contactInfoProperties, true);
//Fax
this._createTextbox("fax", "Fax", contactInfoProperties, false);
//Organization
this._createTextbox("organization", "Organization", contactInfoProperties, false);
//Department
this._createTextbox("department", "Department/Unit", contactInfoProperties, false);
//Role
this._createTextbox("role", "Role/Job title", contactInfoProperties, false);*/
//Website
this._createTextbox("website", data.website, "Website", contactInfoProperties, false, false);
//Address
//this._createTextbox("address", "Address", contactInfoProperties, false);
//TLP
this._createTLP_DDL("tlp", "TLP", contactInfoProperties);
//Create container for CATEGORIES
var contactInfoCategories = domConstruct.create("div", { class: "categories" }, contactInfoContainer);
//Categories heading
var p=domConstruct.create("p", { class: "heading" }, contactInfoCategories);
p.innerHTML = "Categories";
//Alert, Warning & Incident Response
this._createCategory("alert", contactInfoCategories, "Alert, Warning & Incident Response");
//Threat
this._createCategory("threat", contactInfoCategories, "Threat");
//Vulnerability
this._createCategory("vulnerability", contactInfoCategories, "Vulnerability");
//Industry
this._createCategory("industry", contactInfoCategories, "Industry");
//Policy
this._createCategory("policy", contactInfoCategories, "Policy");
//R & D
this._createCategory("rd", contactInfoCategories, "R & D");
//Sharing
this._createCategory("sharing", contactInfoCategories, "Sharing");
//Crime
this._createCategory("crime", contactInfoCategories, "Crime");
//SCADA/Process Control
this._createCategory("scada", contactInfoCategories, "SCADA/Process Control");
//Assurance
this._createCategory("assurance", contactInfoCategories, "Assurance");
//Standards
this._createCategory("standards", contactInfoCategories, "Standards");
//Resilience
this._createCategory("resilience", contactInfoCategories, "Resilience");
//Exercises
this._createCategory("exercises", contactInfoCategories, "Exercises");
//Defence
this._createCategory("defence", contactInfoCategories, "Defence");
//Media handling
this._createCategory("media", contactInfoCategories, "Media handling");
//General PoC
this._createCategory("poc", contactInfoCategories, "General PoC");
//Add remove button
var btnRemove = domConstruct.create("input", { type: "button", id: "btnRemove" + amountContacts, value: "Remove"/*,onclick:"_deleteContact(this)"*/ }, contactInfo);
this.connect(btnRemove, "onclick", dojo.partial(this._deleteContact, btnRemove.id));
},
_createTextbox:function(id, textBoxValue, labelText, parent, checkbox, checkboxChecked)
{
var currentId = id+amountContacts;
var textboxContainer = domConstruct.create("div", {class:"form-item"}, parent);
this._createLabel(currentId, textboxContainer, labelText);
//Create textbox and attach update handler
var textbox = domConstruct.create("input", { type: "text", id: currentId, name: currentId }, textboxContainer);
if (textBoxValue)
textbox.value = textBoxValue;
this.connect(textbox, "onchange", this._updateValue);
if (checkbox) {
this._createCheckbox("inline", textboxContainer, currentId + "_24", "24/7?");
}
},
_createTLP_DDL:function(id, labelText, parent)
{
var currentId = id+amountContacts;
var ddlContainer = domConstruct.create("div", { class: "form-item" }, parent);
this._createLabel(currentId, ddlContainer, labelText);
var ddl = domConstruct.create("select", { name: currentId, id: currentId }, ddlContainer);
//Add options
var option1 = domConstruct.create("option", { val: "-1" }, ddl);
option1.innerHTML = "None";
var option1 = domConstruct.create("option", { val: "1" }, ddl);
option1.innerHTML = "Yes";
var option1 = domConstruct.create("option", { val: "0" }, ddl);
option1.innerHTML = "No";
},
_createCategory:function(id, parent, checkboxText)
{
var currentId = id + amountContacts;
var categoryContainer = domConstruct.create("div", { class: "form-item inline" }, parent);
this._createCheckbox("", categoryContainer, currentId, checkboxText);
},
_createLabel:function(forId, container, labelText)
{
var label = domConstruct.create("label", { for: forId }, container);
label.innerHTML = labelText;
},
_createCheckbox:function(labelClass, container, checkboxId, checkboxText){
var labelCheckbox = domConstruct.create("label", { class: labelClass }, container);
//Create checkbox and attach update handler
var checkbox = domConstruct.create("input", { type: "checkbox", id: checkboxId, name: checkboxId }, labelCheckbox);
this.connect(checkbox, "onchange", this._updateValue);
var span = domConstruct.create("span", {}, labelCheckbox);
span.innerHTML = checkboxText;
},
_deleteContact:function(targetBtnId)
{
var userInput = window.confirm("Are you sure you want to delete this contact?");
if (userInput) {
dojo.destroy(contactContainerPrefixName+targetBtnId[targetBtnId.length-1]);
}
},
_updateValue: function () {
//TODO: Delete test data
var contacts = [];
//The amount of contacts can have changed after deletions, so the global variables might not hold the real value
var actualAmountContacts = 0;
for (var i = 1; i <= amountContacts; i++) {
if (this._isValidContact(i)) {
var currentContact = new Object();
currentContact.fullName = this._getValueById("name" + i);
currentContact.website = this._getValueById("website" + i);
contacts[actualAmountContacts] = currentContact;
actualAmountContacts++;
}
}
this._set("value", contacts);
this.onChange(contacts);
},
_getValueById: function (id) {
var node = dojo.byId(id);
var textValue = (node != null) ? node.value : "";
return textValue;
},
_isValidContact:function(itemNumber){
//If there's no name or telephone then it's not a valid contact
return (this._getValueById("name" + itemNumber) != "" || this._getValueById("phoneOne" + itemNumber) != "" || this._getValueById("phoneTwo" + itemNumber) != "");
},
});
});
UPDATE:
After a lot of test I've realized it's not the domConstruct.create statement which causes the error, the problem is that the form element that has "id:cccp" and to which I want to attach the created elements is null at this point. It is defined in the templateString as you can see in the source code but it's still null in the postCreate method. So the question is now, what event gets triggered when the HTML in the templateString is loaded?
In the end I solved the problem, so I write the workaround here and I hope it helps somebody!
I changed the templateString and added the attribute data-dojo-attach-point=\"form\" to the form that was not being found. Then in the postCreate method I accessed the form using this (this.form ), which worked without a problem. The final implementation for the function turned out as follows:
postCreate: function () {
// call base implementation
this.inherited(arguments);
//this._loadContacts(this.value);
var node = domConstruct.create("fieldset", { id: "test" }, this.form); //this simple create instruction returns undefined here.
//Bind button
this.connect(this.btnAdd, "onclick", dojo.partial(this._createContact, new Object()));
},
I still don't understand why dojo.byId("cccp") would return null, but I'm happy I found a workaround that solved the problem. Cheers!
I'm now trying to do a dynamically created table line , with dijit button, validation box.
The button id and textbox id is generate by index number, so how can my Validation box validator can know which line of validationbox is calling the validator?
Should I make the validator : testcall , being validator : function () {testcall(this.id)}, ????
function createNewRow() {
var tablebodyname = "RPDetailbody" ;
var mytablebody = document.getElementById(tablebodyname);
var thetabletr = document.createElement('tr');
var thetabletd1 = document.createElement('td');
var thetabletd2 = document.createElement('td');
var thetabletd3 = document.createElement('td');
var thisButton = new dijit.form.Button({
label : thelineindex ,
id : "I_del_butt"+thelineindex,
name : "I_del_butt"+thelineindex,
onClick : function() {
document.getElementById(tablebodyname).removeChild(thetabletr);
}
}).placeAt( thetabletd1 ) ;
var thisNumberTextBox = new dijit.form.NumberTextBox({
id : "I_seq_no"+thelineindex ,
name : "I_seq_no"+thelineindex ,
value : thelineindex+1 ,
required : "true",
maxLength : 2,
size : 2 ,
style : "width: 2em;",
missingMessage : "Every line must have sequence number"}).placeAt(thetabletd2) ;
var thisValidationTextBox1 = new dijit.form.ValidationTextBox({
id : "I_pig_code"+thelineindex ,
name : "I_pig_code"+thelineindex ,
type : "text" ,
required : "true",
maxLength : 3,
size : 3,
style : "width: 5em;",
validator : testcall ,
missingMessage : "Must have pigment code" }).placeAt(thetabletd3) ;
thetabletr.appendChild(thetabletd1);
thetabletr.appendChild(thetabletd2);
thetabletr.appendChild(thetabletd3);
mytablebody.appendChild(thetabletr);
thelineindex ++ ;
}
<tbody id="RPDetailbody">
<td><div id="delplace"></div></td>
<td><div id="seqplace"></div></td>
<td><div id="pigcodeplace"></div></td>
</tr>
</tbody>
However I've try to make it as javascript function call to my validator , but I found in the form submittion , using form.isValid() to verify all information can pass validation, it always returns fail !
Here are my validator :
function testcall ( thebtnID ) {
var strlen = thebtnID.length ;
var resultAreaID = "I_pigment_name"+ thebtnID.substring(10, strlen) ;
var pigcode = dijit.byId(thebtnID );
var bNoNameFound = ( "Error" == pigcode.get( "state" ) ) ? false:true;
var query = "thePig=" + encodeURI(pigcode.value );
if( "" == pigcode.value ) {
// for some required=true is not kicking in, so we are forcing it.
bNoNameFound = false;
pigcode._setStateClass();
} else {
if( false == pigcode._focused ) {
console.log( "Checking Pigment..." );
dojo.xhrPost({
url: 'ValidatePigmentInput.php',
handleAs: 'text',
postData: query ,
load: function( responseText ) {
if ( responseText == "no record!" ) {
// setting the state to error since the pigment is already taken
bNoNameFound = false;
pigcode.set( "state", "Error" );
//pigcode.displayMessage( "The Pigment dosen't exist..." );
document.getElementById(resultAreaID).innerHTML = "The Pigment dosen't exist...";
// used to change the style of the control to represent a error
pigcode._setStateClass();
} else {
if ( responseText == "pigment BANNED!" ) {
bNoNameFound = false;
pigcode.set( "state", "Error" );
document.getElementById(resultAreaID).innerHTML = "Pigment BANNED! Please don't use it!";
pigcode._setStateClass();
} else {
bNoNameFound = true;
pigcode.set( "state", "" );
document.getElementById(resultAreaID).innerHTML = responseText;
pigcode._setStateClass();
}
}
},
error: function(responseText) {
document.getElementById(resultAreaID).innerHTML = "Error";
}
});
}
}
return bNoNameFound;
}
You can do:
var thisValidationTextBox1 = new dijit.form.ValidationTextBox({
id: "I_pig_code" + thelineindex,
name: "I_pig_code" + thelineindex,
type: "text",
required: "true",
maxLength: 3,
size: 3,
style: "width: 5em;",
missingMessage: "Must have pigment code"
}).placeAt(thetabletd3);
thisValidationTextBox1.validator = function() {
return testcall(thisValidationTextBox1.id);
};
Ie. you need to pass the id to your testcall() function, but also you need to explicitly override the validator property of the widget.
See this in the Dojo reference guide.