Date "less but not empty" custom search in free-jqgrid - jqgrid

I am using free-jqgrid 4.15.4 for showing the data. There i have a need to search date column with Date less but not empty filter, but it is not filtering correctly. In result it gives me date which are greater than searched date.
Below code is used for custom filter in date column:
customSortOperations: {
dlne: {
operand: "<!=''",
text: "Date less but not empty",
filter:function (options) {
var p = this.p, iCol = p.iColByName[options.cmName], cm = p.colModel[iCol],
newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
cm.formatoptions.newformat :
$(this).jqGrid("getGridRes", "formatter.date.newformat"),
srcformat = cm.formatoptions != null && cm.formatoptions.srcformat ?
cm.formatoptions.srcformat :
$(this).jqGrid("getGridRes", "formatter.date.srcformat"),
fieldData = $.jgrid.parseDate.call(this, srcformat, options.item[options.cmName]),
searchValue = $.jgrid.parseDate.call(this, newformat, options.searchValue);
var retFData = convertD(fieldData), t = new Date(retFData);
if ((retFData.getFullYear() < searchValue.getFullYear()) && (retFData.getMonth() < searchValue.getMonth()) && (retFData.getDate() < searchValue.getDate())) {
return true
}
}
},
}
The convert function that I am using for converting string into date format, is written below:
function convertD(dateField) {
var date = new Date(dateField),
mnth = ("0" + (date.getMonth() + 1)).slice(-2),
day = ("0" + date.getDate()).slice(-2);
// year= (date.getFullYear())
var retVal = [day, mnth, date.getFullYear()].join("/");
return retVal;
}
I have taken the idea from here and made some changes but seems no avail. So requesting community to help on this.

The code of dlne could be fixed to for example the following:
dlne: {
operand: "<!=''",
text: "Date less but not empty",
filter: function (options) {
var p = this.p, iCol = p.iColByName[options.cmName], cm = p.colModel[iCol],
newformat = cm.formatoptions != null && cm.formatoptions.newformat ?
cm.formatoptions.newformat :
$(this).jqGrid("getGridRes", "formatter.date.newformat"),
srcformat = cm.formatoptions != null && cm.formatoptions.srcformat ?
cm.formatoptions.srcformat :
$(this).jqGrid("getGridRes", "formatter.date.srcformat"),
fieldData, searchValue;
// the exact condition to test for "empty" depend on the format of your data
if (!options.item[options.cmName]) {
return false; // ignore empty data
}
fieldData = $.jgrid.parseDate.call(this, srcformat, options.item[options.cmName]);
searchValue = $.jgrid.parseDate.call(this, newformat, options.searchValue);
return fieldData.getFullYear() < searchValue.getFullYear() ||
(fieldData.getFullYear() === searchValue.getFullYear() &&
fieldData.getMonth() < searchValue.getMonth()) ||
(fieldData.getFullYear() === searchValue.getFullYear() &&
fieldData.getMonth() === searchValue.getMonth() &&
fieldData.getDate() < searchValue.getDate());
}
}
see https://jsfiddle.net/OlegKi/51vfn4k9/11/

Related

Is there a way I can make my script more efficient?

I have created the below script to add a timestamp when a cell equals a specific value. This script repeats for each row but it is not efficient. How can I make this simpler and quicker? Below is an extract of the script, it repeats for each row
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('Overview')
var cell = sheet.getRange('H3').getValue()
var sent = sheet.getRange('p3').getValue()
if (cell == "Full" && sent == "") {
sheet.getRange('p3').setValue(new Date())
}
else if (cell == "Open" && sent == "") {
sheet.getRange('p3').setValue("")
}
}
Try this.
function MyFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Overview');
// get range H3:P were H=8, P=16, 9 columns total or index 0 to 8
var data = sheet.getRange(3,8,sheet.getLastRow()-2,9).getValues(); // get range H3:P
var i = 0;
var row = null;
for( i=0; i<data.length; i++ ) {
row = data[i];
if( ( row[0] === "Full" ) && ( row[8] === "" ) ) {
row[8] = new Date();
}
// Your else doesn't do anything if blank set blank ??
row.splice(0,8); // extract only column P
}
sheet.getRange(3,16,data.length,1).setValues(data);
}
Try using setvalues() method of class range
function MyFunction() {
const ss = SpreadsheetApp.getActive()
const sh = ss.getSheetByName('Overview');
const rg = sh.getDataRange();
const vs = rg.getValues();
let vo = vs.map(r => {
if( r[7] == "Full") r[15]=new Date()
if( r[7] == "Open") r[15]='';
return [r[15]];
});
sh.getRange(2,16,vo.length,1).setValues(vo);
}

Dynamics crm + plugin logic to update zero values

I need to perform the sum of each field across multiple records of the same entity and update the values on the same entity. Along with this I also need to store its formula.
AttributeList = { "price ", "quantity", "contact.revenue", "opportunity.sales"}
Below is the logic
foreach (var attribute in attributeList)
{
Decimal fieldSum = 0;
string computedNote = string.Empty;
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
if (entity.Attributes[attribute] != null)
{
string type = entity.Attributes[attribute].GetType().Name;
Decimal attrValue = 0;
if (type == "AliasedValue")
{
AliasedValue aliasedFieldValue = (entity.GetAttributeValue<AliasedValue>(attribute));
attrValue = aliasedFieldValue.Value.GetType().Name == "Decimal" ? (Decimal)aliasedFieldValue.Value : (Int32)aliasedFieldValue.Value;
}
else
{
attrValue = entity.Attributes[attribute].GetType().Name == "Decimal" ? entity.GetAttributeValue<Decimal>(attribute) : entity.GetAttributeValue<Int32>(attribute);
}
fieldSum += attrValue;
computedNote += $"+{Convert.ToInt32(attrValue).ToString()}";
}
}
else
{
computedNote += $"+0";
}
}
Entity formula = new Entity("formula");
if (fieldSum != 0)
{
if (attribute.Contains("opportunity"))
{
opportunity[attributeName] = fieldSum;
entityName = Opportunity.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
else if (attribute.Contains("contact"))
{
contact[attributeName] = fieldSum;
entityName = Contact.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
else
{
mainentity[attribute] = fieldSum;
entityName = mainEntity.EntityLogicalName;
attributeName = attribute;
recordId = Id;
}
formula.Attributes["ice_entity"] = entityName;
formula.Attributes["ice_attribute"] = attributeName;
formula.Attributes[entityName + "id"] = new EntityReference(entityName, recordId);
formula.Attributes["ice_computednote"] = computedNote.Remove(0, 1);
requestsCollection.Entities.Add(formula);
}
}
requestsCollection.Entities.Add(opportunity);
requestsCollection.Entities.Add(contact);
requestsCollection.Entities.Add(mainentity);
Values in both records could be as follows
Record 1
Price = 500
Quantity = 25
Revenue = 100
Sales = 10000
Volume = 0
Record 2
Price = 200
Quantity = 10
Revenue = 100
Sales = -10000
Volume = 0
Record 3 (Values after calculation that are to be updated in the third entity and Formula to be stored mentioned in brackets)
Price = 700 Formula = (500+200)
Quantity = 35 Formula = (25+10)
Revenue = 200 Formula =(100+100)
Sales = 0 Formula =(10000 + (-10000))
Volume = 0 No Formula to be created
I am checking if the fieldsum is not equal to zero (to update both positive and negative values) and then updating the values in the respective entity. However for values that became zero after the calculation. I also need to update them and create formula for the same. Avoiding the values that were zero by default.
As shown in above example, I want to update sales field value and create formula record for the same as '10000+-10000' but do not want volume field value to be updated or the formula to be created for it. How can i embed this logic in my code?
Add a flag (updateFormula) to indicate whether checksum and formula required to update in related entities. Then, instead of checking fieldSum != 0, check updateFormula is true to update the related records.
attributeList = { "price", "quantity", "contact.revenue", "opportunity.sales"}
foreach (var attribute in attributeList)
{
Decimal fieldSum = 0;
string computedNote = string.Empty;
bool updateFormula = false;
foreach (var entity in mainEntityList)
{
if (entity.Contains(attribute))
{
if (entity.Attributes[attribute] != null)
{
string type = entity.Attributes[attribute].GetType().Name;
Decimal attrValue = 0;
if (type == "AliasedValue")
{
AliasedValue aliasedFieldValue = (entity.GetAttributeValue<AliasedValue>(attribute));
attrValue = aliasedFieldValue.Value.GetType().Name == "Decimal" ? (Decimal)aliasedFieldValue.Value : (Int32)aliasedFieldValue.Value;
}
else
{
attrValue = entity.Attributes[attribute].GetType().Name == "Decimal" ? entity.GetAttributeValue<Decimal>(attribute) : entity.GetAttributeValue<Int32>(attribute);
}
fieldSum += attrValue;
computedNote += Convert.ToInt32(attrValue).ToString();
updateFormula = true;
}
}
else
{
computedNote += 0;
}
}
Entity formula = new Entity("formula");
if (updateFormula)
{
// Logic to update formula and checksum
}
}

stylescombo plugins with multiple class selection

I merged the stylesheetparser and the stylescombo plugins and want to select mutiple classes from the combo. I made some changes in the onOpen and the onClick functions:
onOpen: function() {
var selection = editor.getSelection(),
selectedElement = selection.getSelectedElement(),
selectedRanges = !selectedElement && selection.getRanges(),
selectedText = !selectedElement && selection.getSelectedText(),
nativeRange,
elementPath = editor.elementPath(),
element,
counter = [ 0, 0, 0, 0 ];
this.showAll();
this.unmarkAll();
for ( var name in styles ) {
var style = styles[ name ],
type = style._.type;
if(type == CKEDITOR.STYLE_OBJECT && (selectedElement || selectedText))
element = !selectedText ? selectedElement : selectedText;
else if((type == CKEDITOR.STYLE_BLOCK || type == CKEDITOR.STYLE_INLINE) && !selectedText && !selectedElement && selectedRanges[ 0 ] && selectedRanges[ 0 ].getCommonAncestor( 1 ))
element = selectedRanges[ 0 ].getCommonAncestor( 1 ).getAscendant( style.element );
else if(type == CKEDITOR.STYLE_INLINE && selectedText && !selectedElement)
element = selectedText;
if(element != null) {
if(style.checkApplicable( elementPath, editor, editor.activeFilter )) {
counter[ type ]++;
var classes = !selectedText ? element.getAttribute( 'class' ) : null,
classArr = classes != null ? classes.split(' ') : [];
if(classArr.length > 0) {
for(var i = 0; i < classArr.length; i++) {
if(classArr[i] == style._.definition.attributes['class'])
this.mark( name );
}
}
}
else
this.hideItem( name );
}
}
if ( !counter[ CKEDITOR.STYLE_BLOCK ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_BLOCK ) ] );
if ( !counter[ CKEDITOR.STYLE_INLINE ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_INLINE ) ] );
if ( !counter[ CKEDITOR.STYLE_OBJECT ] )
this.hideGroup( lang[ 'panelTitle' + String( CKEDITOR.STYLE_OBJECT ) ] );
},
onClick: function( value ) {
editor.focus();
editor.fire( 'saveSnapshot' );
var style = styles[ value ],
type = style._.type,
selection = editor.getSelection(),
selectedElement = selection.getSelectedElement(),
selectedRanges = !selectedElement && selection.getRanges(),
selectedText = !selectedElement && selection.getSelectedText(),
element;
if(type == CKEDITOR.STYLE_OBJECT && (selectedElement || selectedText))
element = !selectedText ? selectedElement : selectedText;
else if((type == CKEDITOR.STYLE_BLOCK || type == CKEDITOR.STYLE_INLINE) && !selectedText && !selectedElement && selectedRanges[ 0 ] && selectedRanges[ 0 ].getCommonAncestor( 1 ))
element = selectedRanges[ 0 ].getCommonAncestor( 1 ).getAscendant( style.element );
else if(type == CKEDITOR.STYLE_INLINE && selectedText && !selectedElement)
element = selectedText;
if(element != null) {
var classes = !selectedText ? element.getAttribute( 'class' ) : null,
classArr = classes != null ? classes.split(' ') : [],
selClass = style._.definition.attributes['class'],
styleClasses = CKEDITOR.tools.clone( style );
if(classArr.length > 0 && contains(classArr, selClass) && !selectedText) {
var newClassArr = new Array();
for(var i = 0; i < classArr.length; i++) {
if(classArr[i] != selClass)
newClassArr.push(classArr[i]);
}
if(newClassArr.length == 0) {
editor.removeStyle( styleClasses );
}
else {
styleClasses._.definition.attributes['class'] = newClassArr.join(' ');
editor.applyStyle( styleClasses );
}
}
else {
classArr.push(selClass);
styleClasses._.definition.attributes['class'] = classArr.join(' ');
editor.applyStyle( styleClasses );
}
}
editor.fire( 'saveSnapshot' );
},
It works for block elements and images (didn't checked fake elements), you can select and deselect all classes you want. But I have some trouble with inline elements.
If I click inside a block element, it lists all classes for this element and I can select/deselect what I want/need. If I click inside an inline element, nothing happends. Can getAscendant() not find inline element tags?
If I select text, it lists all classes for inline elements. But I want span classes only and not e.g. strong classes. Classes for the strong tag should only available if I select a strong element. Is it possible? How can I differentiate different inline elements?
Why anchors are objects and not inline elements? If I double click an anchor and close the link dialog, I can select an anchor class.
How to disable the combo, if no classes are available? I can not find the right place.
How to disable the combo close on a class selection? If the selected class is set after close, forget this question - I can live with it :-)
Here is a demo: http://webutler.de/test/index.php?lang=en
The complete file: test/plugins/cssclasscombo/plugin.js
The plugin as zip: test/plugins/cssclasscombo.zip
If you try the plugin, set
config.contentsCss = ['contents.css']; // <= it reads the classes from this file
config.extraPlugins = 'cssclasscombo';
config.removePlugins = 'stylescombo';
config.stylesSet = [];
config.allowedContent = true;
// the plugin works with indent and justify classes =>
config.justifyClasses = [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ];
config.indentClasses = [ 'indent1', 'indent2', 'indent3', 'indent4', 'indent5' ];
to your config and use this CSS file: http://www.webutler.de/test/contents.css
Thanx for help
It's not perfect, but the plugin works now. If you can need it, here is the download:
http://webutler.de/download/ckeditor_plugins/cssclasscombo.zip
Settings in your config.js:
config.removePlugins = 'stylescombo';
config.extraPlugins = 'cssclasscombo';
config.stylesSet = [];
config.contentsCss = ['contents.css']; // <= classes are read from this file(s)

LINQ query fails with nullable variable ormlite

I'm trying to write following LINQ query using ServiceStack Ormlite.
dbConn.Select<Product>(p => p.IsActive.HasValue && p.IsActive.Value)
Here, Product is my item class and "IsActive" is Nullable Bool property in that class. When this line executes it always throws "InvalidOperationException" with the message
variable 'p' of type '' referenced from scope '', but it is not defined
I tried different variants as following but still same exception result
dbConn.Select<Product>(p => p.IsActive.HasValue == true && p.IsActive.Value == true)
dbConn.Select<Product>(p => p.IsActive != null && p.IsActive.Value == true)
But if I just write
dbConn.Select<Product>(p => p.IsActive.HasValue)
then it works.
I'm puzzled what is the problem? Is this servicestack ormlite issue?
My answer can handle Nullable value like "value" and "HasValue" with servicestack ormlite. And But also with datetime nullable ,like 'createdate.value.Year'.
you must change two place.
modify VisitMemberAccess method:
protected virtual object VisitMemberAccess(MemberExpression m)
{
if (m.Expression != null)
{
if (m.Member.DeclaringType.IsNullableType())
{
if (m.Member.Name == nameof(Nullable<bool>.Value))
return Visit(m.Expression);
if (m.Member.Name == nameof(Nullable<bool>.HasValue))
{
var doesNotEqualNull = Expression.NotEqual(m.Expression, Expression.Constant(null));
return Visit(doesNotEqualNull); // Nullable<T>.HasValue is equivalent to "!= null"
}
throw new ArgumentException(string.Format("Expression '{0}' accesses unsupported property '{1}' of Nullable<T>", m, m.Member));
}
if (m.Member.DeclaringType == typeof(DateTime))
{
var ExpressionInfo = m.Expression as MemberExpression;
if (ExpressionInfo.Member.DeclaringType.IsNullableType())
{
if (ExpressionInfo.Member.Name == nameof(Nullable<bool>.Value))
{
var modelType = (ExpressionInfo.Expression as MemberExpression).Expression.Type;
var tableDef = modelType.GetModelDefinition();
var columnName = (ExpressionInfo.Expression as MemberExpression).Member.Name;
var QuotedColumnName = GetQuotedColumnName(tableDef, columnName);
if (m.Member.Name == "Year")
{
return new PartialSqlString(string.Format("DATEPART(yyyy,{0})", QuotedColumnName));
}
if (m.Member.Name == "Month")
return new PartialSqlString(string.Format("DATEPART(mm,{0})", QuotedColumnName));
}
if (ExpressionInfo.Member.Name == nameof(Nullable<bool>.HasValue))
{
var doesNotEqualNull = Expression.NotEqual(ExpressionInfo.Expression, Expression.Constant(null));
return Visit(doesNotEqualNull); // Nullable<T>.HasValue is equivalent to "!= null"
}
}
else
{
var modelType = ExpressionInfo.Expression.Type;
var tableDef = modelType.GetModelDefinition();
var columnName = ExpressionInfo.Member.Name;
var QuotedColumnName = GetQuotedColumnName(tableDef, columnName);
if (m.Member.Name == "Year")
return new PartialSqlString(string.Format("DATEPART(yyyy,{0})", QuotedColumnName));
if (m.Member.Name == "Month")
return new PartialSqlString(string.Format("DATEPART(mm,{0})", QuotedColumnName));
}
}
if (m.Expression.NodeType == ExpressionType.Parameter || m.Expression.NodeType == ExpressionType.Convert)
{
var propertyInfo = (PropertyInfo)m.Member;
var modelType = m.Expression.Type;
if (m.Expression.NodeType == ExpressionType.Convert)
{
var unaryExpr = m.Expression as UnaryExpression;
if (unaryExpr != null)
{
modelType = unaryExpr.Operand.Type;
}
}
var tableDef = modelType.GetModelDefinition();
if (propertyInfo.PropertyType.IsEnum)
return new EnumMemberAccess(
GetQuotedColumnName(tableDef, m.Member.Name), propertyInfo.PropertyType);
return new PartialSqlString(GetQuotedColumnName(tableDef, m.Member.Name));
}
}
var member = Expression.Convert(m, typeof(object));
var lambda = Expression.Lambda<Func<object>>(member);
var getter = lambda.Compile();
return getter();
}
modify VisitLambda method :
protected virtual object VisitLambda(LambdaExpression lambda)
{
if (lambda.Body.NodeType == ExpressionType.MemberAccess && sep == " ")
{
MemberExpression m = lambda.Body as MemberExpression;
if (m.Expression != null)
{
string r = VisitMemberAccess(m).ToString();
if (m.Member.DeclaringType.IsNullableType())
return r;
return string.Format("{0}={1}", r, GetQuotedTrueValue());
}
}
return Visit(lambda.Body);
}
This is nature of the Linq. In order to achieve what you need, you will need to use two where closes:
dbConn.Where<Product>(p => p.IsActive.HasValue).Where(p=>p.Value==true);

Backbone JS: Validating required nested attributes/models?

If I have a Backbone model who's defaults object looks like this:
defaults {
"id" : null
"name" : null,
"url" : null,
"admin" : {
"id" : null,
"email" : null
}
}
is there a recommended way to validate the presence of something like admin[id]? We've written a method that makes the attempt, but it keeps puking (especially on new model creation) on null values, or if data is fetched from our DB with null values that are expected to be required (we are laying this app on top of existing data).
Here's our method for validating the presence of required fields:
validatePresence = function(requiredAttrs, submittedAttrs, errorsArr) {
var regex = new RegExp(/[a-zA-Z0-9_]+|(?=\[\])/g),
attrStack = null,
val = null,
name = null;
for( var l = requiredAttrs.length; --l >= 0; ) {
attrStack = requiredAttrs[l].match(regex);
val = submittedAttrs[attrStack.shift()];
while(attrStack.length > 0) {
console.log(requiredAttrs[l]);
val = val[attrStack.shift()];
}
if( val === undefined ) { continue; }
name = requiredAttrs[l];
if( val === null || !val.length) {
if( !errorsArr[name] ) {
errorsArr[name] = [];
}
errorsArr[name].push("Oops, this can't be empty");
}
}
return errorsArr;
}
And here's the way we call it from within a BB model:
validate: function(attrs) {
var requiredAttributes = ["name","admin[id]"],
errors = {};
errors = validatePresence(requiredAttributes, attrs, errors);
}
That method likes to choke on things like "admin[id]". Any help is apprecaited.
If you're not dead set on the bracket notation for your required attributes, you could draw some inspiration from this Q&A to simplify your validation.
Let's add a helper method to _ to extract the value of a given attribute:
_.findprop = function(obj, path) {
var args = path.split('.'), i, l=args.length;
for (i=0; i<l; i++) {
if (!obj.hasOwnProperty(args[i]))
return;
obj = obj[args[i]];
}
return obj;
}
Your validate method can then be rewritten as:
validate: function(attrs) {
var requiredAttributes = ["name","admin.id"],
errors = {}, i, l, v, attr;
for (i=0, l=requiredAttributes.length; i<l; i++) {
attr = requiredAttributes[i];
v = _.findprop(attrs, attr);
//checks if the value is truthy, to be adapted to your needs
if (v) continue;
errors[attr] = errors[attr] || [];
errors[attr].push("Oops, this can't be empty");
}
return errors;
}
And a demo http://jsfiddle.net/FrtHb/2/

Resources