Javascript event on XPage ViewColumnHeader Sort - sorting

I'm working with XPages recently and I'm having trouble with the sorting of data in container controls. I've been able to get data to display well through multiple solutions, view panels, data tables, and repeat controls, but sorting seems to only work well through view panels. (After doing some research and realizing that Java.Util.TreeMap provides some utility for other containers). However, the problem I'm having is that the images that view column headers add for sorting aren't what I want.
So, my question is this:
Is there any way to either change where XPages looks for those images (Knowing I can set a class on that image tag through Image.ViewColumnHeaderSort doesn't help due to not having access to the event) or can I access the event in order to set a scoped variable that I could use to compute a class on my TH elements.
Thanks in advance,
Aaron Brake
4CTechnologies

Here is a workaround for this problem, it uses the URL parameter for sorting the view panel columns.
Example XPage:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:script src="/jssViewSort.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:viewPanel rows="30" id="viewPanel2">
<xp:this.facets>
<xp:pager partialRefresh="true" layout="Previous Group Next"
xp:key="headerPager" id="pager2">
</xp:pager>
</xp:this.facets>
<xp:this.data>
<xp:dominoView var="view1" viewName="_YOUR_VIEW_"></xp:dominoView>
</xp:this.data>
<xp:viewColumn columnName="Form" id="viewColumn3">
<xp:viewColumnHeader value="Form" id="viewColumnHeader3" iconSrc="#{javascript:getViewSortIcon(this)}">
<xp:this.attrs>
<xp:attr name="onclick">
<xp:this.value><![CDATA[#{javascript:getViewSortLink(this)}]]></xp:this.value>
</xp:attr>
</xp:this.attrs>
</xp:viewColumnHeader>
</xp:viewColumn>
</xp:viewPanel>
</xp:view>
The view used has a sortable column named "Form", sortable in both directions.
And here is the SSJS library, unoptimized and undocumented:
/**
* returns a link for sorting a view panel
*
* #author Sven Hasselbach
* #version 0.1
*/
function getViewSortLink( colHeader:com.ibm.xsp.component.xp.XspViewColumnHeader ){
var col:com.ibm.xsp.component.xp.XspViewColumn = colHeader.getParent();
var vp:com.ibm.xsp.component.xp.XspViewPanel = col.getParent();
var ds:com.ibm.xsp.model.domino.DominoViewData = vp.getDataSource();
var curSortOrder = vp.getDataSource().getSortOrder();
var sortCol = context.getUrlParameter("sortColumn");
var sortOrder = context.getUrlParameter("sortOrder");
if( sortCol === col.getColumnName() ){
if( curSortOrder === null || curSortOrder === "" )
sortOrder = "ascending";
if( curSortOrder === "ascending" )
sortOrder = "descending";
if( curSortOrder === "descending" )
sortOrder = ""
}else{
sortOrder = "ascending";
sortCol = col.getColumnName();
}
return "window.location='" + context.getUrl().getPath() + "?sortColumn=" + sortCol + "&sortOrder=" + sortOrder + "'";
}
/**
* returns a view icon for sorting
*
* #author Sven Hasselbach
* #version 0.1
*/
function getViewSortIcon( colHeader:com.ibm.xsp.component.xp.XspViewColumnHeader ){
var col:com.ibm.xsp.component.xp.XspViewColumn = colHeader.getParent();
var vp:com.ibm.xsp.component.xp.XspViewPanel = col.getParent();
var ds:com.ibm.xsp.model.domino.DominoViewData = vp.getDataSource();
var curSortOrder = vp.getDataSource().getSortOrder();
var sortCol = context.getUrlParameter("sortColumn");
if( sortCol !== col.getColumnName() )
return "http://www.google.de/images/icons/product/chrome-48.png";
if( curSortOrder === "ascending" )
return "https://www.google.com/intl/de/images/icons/feature/alert-b42.png"
if( curSortOrder === "descending" )
return "https://www.google.com/intl/de/images/icons/product/calendar-42.png"
return "http://www.google.de/images/icons/product/chrome-48.png";
}
The image can be adjusted with CSS.
Hope this helps!

Related

How to change SharePoint List Views Style using CSOM Programmatically in C#

I have created list view using below code
ViewCreationInformation creationInfo = new ViewCreationInformation();
creationInfo.Title ="MyView";
creationInfo.RowLimit = 10;
creationInfo.ViewFields = viewFields.ToArray();
creationInfo.ViewTypeKind = "HTML";
viewCollection.Add(creationInfo);
context.ExecuteQuery();
I want to change the style using CSOM. But there is no option to change the style using client DLL.Though I tried to update ListViewXML is not getting updated.Kindly help me on this.
////Please add below code with your code
//// Update view style
/*
* 0-Basic Table
* 14-Document Details
* 15-Newsletter
* 16-Newsletter, no lines
* 17-Shaded
* 20-Preview Pane
*/
ViewCollection oView = list.Views;
int styleId = 17;
foreach (View v in oView)
{
if (v.Title == "MyView")
{
ctx.Load(v);
ctx.ExecuteQuery();
XmlDocument doc = new XmlDocument();
doc.LoadXml(v.ListViewXml);
XmlElement element = (XmlElement)doc.SelectSingleNode("//View//ViewStyle");
if (element == null)
{
element = doc.CreateElement("ViewStyle");
element.SetAttribute("ID", styleId.ToString());
doc.DocumentElement.AppendChild(element);
}
else
{
element.SetAttribute("ID", styleId.ToString());
}
v.ListViewXml = doc.FirstChild.InnerXml;
v.Update();
ctx.ExecuteQuery();
break;
}
}

How to reference styles properly in InDesign Scripting?

I would like to know what is the proper way to reference a character style, a paragraph style or any other style in InDesign Scripting.
Please keep in mind that they could be under style group.
This should do it. Have a look at the function get_style.
update: use id instead of names
// written for
// http://stackoverflow.com/questions/19302941/how-to-reference-styles-properly-in-indesign-scripting
// author: #fabiantheblind
// license: wtfpl http://www.wtfpl.net
main();
function main(){
var doc = app.documents.add();// add a document
// create some styles
doc.paragraphStyles.add({name:"one"});
doc.paragraphStyles.add({name:"two"});
doc.paragraphStyles.add({name:"three"});
// add a group
var grp1 = doc.paragraphStyleGroups.add({name:"grp1"});
// add a style in the group
grp1.paragraphStyles.add({name:"four"});
// add a group in the group
var grp2 = grp1.paragraphStyleGroups.add({name:"grp2"});
// add a style in the group in the group
var parstylefive = grp2.paragraphStyles.add({name:"five"});
var fiveid = parstylefive.id;
var pg = doc.pages[0];// first page in new doc
var tf= pg.textFrames.add({geometricBounds:[0,0,100,100]});// add a textframe
tf.contents = TextFrameContents.PLACEHOLDER_TEXT;// add some cintent
var astyle = get_style(doc, fiveid);//get a style by name
if(astyle === null){
// error
alert("There is no style with that name");
}else{
// woohoo! \o/
tf.paragraphs.everyItem().appliedParagraphStyle = astyle;
}
}
/**
* This loops through all paragraph styles and returns one by his name
* could be rewritten for allCharacterStyles, allObjectStyles etc
*/
function get_style(d, id){
var thestyle = null;// result
for(var i = 0; i <d.allParagraphStyles.length;i++ ){
var onestyle = d.allParagraphStyles[i]; // isolate
if(id === onestyle.id){
thestyle = onestyle;// found it
} // end of check
} // end of loop i
// if we did not finds it we return null else Object ParagraphStyle
return thestyle;
}
I took an approach where you have to work with what I call the Fully Qualified Name (FQN) of a style, which is combination of all the groups and the style name separated by a pipe (|)
I've implemented the two following function in our code. They can be used with all type of styles with just a little bit of modification to the getStyleByFullyQualifiedName() function to support the other 4 types.
//getStyleFullyQualifiedName allow you to retrieve the style FQN,
//by providing a style object. Combine the name of the style and
//groups together separated by pipe (|).
function getStyleFullyQualifiedName(object){
var objectName = object.name;
if(object.parent.constructor.name != "Document"){
return getStyleFullyQualifiedName(object.parent) + "|" + objectName;
}
return objectName;
}
function getStyleByFullyQualifiedName(paragraphStyleFQN, document){
var tmp = paragraphStyleFQN.split("|");
var object = document;
for(var i=0; i < (tmp.length - 1); i++){
if(object.isValid){
object = object.paragraphStyleGroups.itemByName(tmp[i]);
}else{
return null;
}
}
if(!object.isValid){
return null;
}
object = object.paragraphStyles.itemByName(tmp[(tmp.length - 1)]);
if(!object.isValid){
return null;
}
return object;
}
//Assuming you have a style "Heading 1" under group "Title" and "Center.
//You can retrieve the style object like this.
var styleObject = getStyleByFullyQualifiedName("Title|Center|Heading 1", app.activeDocument);
//You can get the style FQN when you have a style object like this.
var styleFQN = getStyleFullyQualifiedName(styleObject);
alert("Valid: " + styleObject.isValid + " styleFQN: " + styleFQN);

Devexpress Gridview Hide Editform in asp.net mvc

If my CustomerName FieldName equals to "MyCustomer" , i want to hide editing for that row.
If customername == "MyCustomer , hide column editing.
How can i hide column editing according to "MyCustomer"?
settings.Columns.Add(s =>
{
s.FieldName = "CustomerName";
s.Caption = "Customer";
s.Name = "CustomerColumn";
s.ColumnType = MVCxGridViewColumnType.ComboBox;
var comboBoxProperties = s.PropertiesEdit as ComboBoxProperties;
comboBoxProperties.DataSource =Model.CustomerList;
comboBoxProperties.TextField = "Customer_Name";
comboBoxProperties.ValueField = "Customer_Id";
comboBoxProperties.ValueType = typeof(int);
comboBoxProperties.ClientInstanceName = "CustomerColumn";
});
Any help will be appreaciated with points.
settings.CommandButtonInitialize = (s, e) => {
if (e.ButtonType == ColumnCommandButtonType.Edit) {
MVCxGridView g = s as MVCxGridView;
var value = (int)g.GetRowValues(e.VisibleIndex, "RowFieldName"); //use a correct field name and cast a resultant value to a correct value type
e.Visible = value > 10; // for example, only
}
};
Fortunately , i have myself.I found a solution.
It works.Hope this helps who has the same problem in the future.

Magento jQuery Ajax search issue

I am trying to implement a customize Magento Advanced Search, using jQuery and Ajax.
The search works something like this:
1) There are 2/3 options to select size
2) 6 options to narrow down search result
3) A text box to enter keywords etc
There is no submit button, that means, search starts when user clicks on any size and/or Options or enter more than 3 char in search text box, search starts, an ajax request is sent to server.
If user clicks on another option or say type in another character, I use to abort previous search using search_request.abort() and set previous search to null.
When you search for first couple of times, it works fine, search returns result and if no result is found, proper message is displayed.But, after after couple of requests, it starts failing. Like if I click on options in short interval (I mean, search is fired frequently)). Some times, it fails without any reason and sometimes it fails, and when I click on the same option a couple of seconds later, it display the results.
Sometimes, when the search fails or there is no result.
It displays the incomplete message in result area like:
Where as it should look like :
Search when it returns result:
Search when it fails
My question is:
1) do you think it might be failing because too many requests are submitted too frequently? I mean is there something related to Magento settings?
2) What can I do to correct this?
Here is the jQuery code:
<script type="text/javascript">
function search(textfield)
{
j('#slides').html("<img src='<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>skin/frontend/luckybloke/luckybloke/images/ajax-loader.gif' class='no-results-found' style='width:100px !important; padding-top:10px !important;text-align:center;margin-left: 43%;' />");
var form = j("#form-validate");
var action = form.attr("action");
var fieldAdded = Array();
var searchData = '';
var searchVal = '';
var sizeSelected = '';
var searchArray = new Array();
var searchCtr = 0;
var tmp = new Array();
if(typeof search_request =='object' && search_request!=null){
search_request.abort();
search_request = null;
j('#slides').html("<img src='<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>skin/frontend/luckybloke/luckybloke/images/ajax-loader.gif' class='no-results-found' style='width:100px !important; padding-top:10px !important;text-align:center;margin-left: 43%;' />");
}
j('.input-search').each(function(index,domEle){
var eleID = "#"+j(domEle).attr("id");
var curEle= j(domEle).attr("name");
fieldAdded.push(curEle.replace('[]',''));
////consloe.log(eleID);
if((j(eleID).val()!='' || !jQuery.inArray(curEle,fieldAdded))&& eleID!='#name'){
if(searchVal==''){
searchVal=searchVal+j(eleID).val();
}
if(searchData==''){
searchData = searchData+""+curEle+"="+j(eleID).val();
}else{
searchData = searchData+"&"+curEle+"="+j(eleID).val();
}
searchArray[searchCtr] = j(eleID).val();
searchCtr++;
}
//add description field to search query
tmp[curEle] = j(eleID).val();
}
});
if(searchVal==''){
}
if(j("#name").val()=='brand, style, keyword'){
var val = '';
}else{
val = j("#name").val();
}
searchData = searchData+"&search_keywords="+val;
//toggleFields(sizeSelected, searchArray);
search_request = j.ajax({
type:'get',
url:action,
data:searchData,
cache: false,
dataType:'html',
success:searchComplete
});
return;
}
function searchComplete(responseText, statusText, xhr, $form)
{
var no_item_msg = 'No product found matching your search criteria.';
if(statusText=='success'){
var isFound = responseText.toString().search(new RegExp(/no items found/i));
//alert(isFound+''+responseText.toString());
if((isFound>0 || responseText.length == 0) && search_request ){
j("div#slides").html("<span class='no-results-found'>"+no_item_msg+"</span>");
// j("div#slides").html("<span class='no-results-found'>"+no_item_msg+"</span>");
/*j("div#lb-product-list").block({message:no_item_msg});
setTimeout('j("div#lb-product-list").unblock()', 2000);*/
}else{
var dataToFill = j("div#lb-product-list");
var isFound = responseText.toString().search(new RegExp(/JUST_ONE/i));
if(isFound>=0){
responseText = responseText.replace(/just_one/i,'');
}else{
j.getScript("<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB); ?>js/carousol.js", function() {});
}
dataToFill.html(j(responseText).children());
search_request = null;
}
//reset the css attribute's position value, as ui blocking seems to be affecting positioning of elements are unblocking
j("div#lb-product-list").css("position",'');
return true;
}
}
</script>

A Dual Ajax ListBox

Do you guys know of any .net controls with 2 listboxes that can move items from left to right and vice versa?!
Like a dual listbox type of thing.
I have already looked at http://ajaxlistbox.codeplex.com/ it seems to be pretty sweet.
just want to know any suggestions.
Here's a way:
Make two ListBoxes, the first shows all available item, the second shows what the user chooses. You also need a TextBox to hold a copy of the chosen items, since it is not possible to retrieve ListBox items in C# if they were added via javascript. Make the TextBox hidden, so the user cannot accidentally mess up the items.
Click an item in the first listbox and it appears in the second "chosen" listbox. Click on chosen item in the second list and it disappears. You could alter this so items are removed from the first list after being chosen.
I call AddJavascript from my Page_Load method.
ListBoxFilteredProfiles is my first TextBox, ListBoxSelectedProfiles is the second.
private void AddJavascript()
{
// This javascript function adds the item selected in one listbox to another listbox.
// Duplicates are not allowed, items are inserted in alphabetical order.
string OnChangeProfileListBoxJavascript =
#"<script language=JavaScript>
<!--
function OnChangeSelectedProfiles()
{
var Target = document.getElementById('" + ListBoxSelectedProfiles.ID + #"');
var Source = document.getElementById('" + ListBoxFilteredProfiles.ID + #"');
var TB = document.getElementById('" + TextBoxProfiles .ID + #"');
if ((Source != null) && (Target != null)) {
var newOption = new Option(); // a new ListItem
newOption.text = Source.options[ Source.options.selectedIndex ].text;
newOption.value = Source.options[ Source.options.selectedIndex ].value;
var jj = 0;
for( jj = 0; jj < Target.options.length; ++jj ) {
if ( newOption.text == Target.options[ jj ].text ) { return true; } // don't add if already in the list
if ( newOption.text < Target.options[ jj ].text ) { break; } // add the new item at this position
}
for( var kk = Target.options.length; kk > jj; --kk ) { // bump the remaining list items up one position
var bumpItem = new Option();
bumpItem.text = Target.options[ kk-1 ].text; // copy the preceding item
bumpItem.value = Target.options[ kk-1 ].value;
Target.options[ kk ] = bumpItem;
}
Target.options[ jj ] = newOption; // Append the item in Target
if (TB != null) {
// Copy all the selected profiles into the hidden textbox. The C# codebehind gets the selections from the textbox because listbox values added via javascript are not accessible.
TB.value = '';
for( var jj= 0; jj < Target.options.length; ++jj ) { TB.value = TB.value + Target.options[ jj ].value + '\n'; }
}
}
}
// -->
</script> ";
// This javascript function removes an item from a listbox.
string OnChangeRemoveListBoxItemJavascript =
#"<script language=JavaScript>
<!--
function OnChangeRemoveProfile()
{
var Target = document.getElementById('" + ListBoxSelectedProfiles.ID + #"');
var TB = document.getElementById('" + TextBoxProfiles.ID + #"');
Target.remove( Target.options.selectedIndex );
TB.value = '';
// Copy all the selected profiles into the hidden textbox. The C# codebehind gets the selections from the textbox because listbox values added via javascript are not accessible.
for( var jj= 0; jj < Target.options.length; ++jj ) { TB.value = TB.value + Target.options[ jj ].value + '\n'; }
}
// -->
</script> ";
ClientScript.RegisterStartupScript( typeof(Page), "OnChangeSelectedProfiles", OnChangeProfileListBoxJavascript );
ClientScript.RegisterStartupScript( typeof(Page), "OnChangeRemoveProfile", OnChangeRemoveListBoxItemJavascript );
ListBoxFilteredProfiles.Attributes.Add("onchange", "OnChangeSelectedProfiles()" );
ListBoxSelectedProfiles.Attributes.Add("onchange", "OnChangeRemoveProfile()" );
}

Resources