Friday, May 20, 2011

Using JQuery to handle Add, Add All, Remove, Remove All, Up, Down process for two Select Box into Editor Part of custom Web Part

There was a requirement to develop a UI for Editor Part of my custom Web Part to add 2 select box and adding Add, Add All, Remove, Remove All functionality. Also i had to save selected images as webpart property and display into webpart on apply. UI is something like given image.

I added all UI from editor part class but for movements i used JQuery but when i try to save the data on Apply event i got an error:
Invalid postback or callback argument. Event validation is enabled using

After so much of googling and trying mutiple solutions i got in blogs finally i gone through this error by putting hidden text box and putting all selected image ids into it.

Here is code

As we had to create all controls at runtime into Editor Part Code also we had to send the ClientID for the controls which will be used by JQuery code added into js file so i added small script block to send ids to JQuery

Into CreateChildControls() of Editor Part

this.txtHiddenIDs = new TextBox();
this.txtHiddenIDs.ID = "hdnIDs";
this.txtHiddenIDs.Style.Add(HtmlTextWriterStyle.Visibility, "hidden");
this.txtHiddenIDs.Style.Add(HtmlTextWriterStyle.Position, "absolute");
this.Controls.Add(txtHiddenIDs);

if (!Page.ClientScript.IsClientScriptBlockRegistered("jscript"))
{
string jscript = "
<script type="text/javascript"><span style="font-size:85%;"> var $lstBoxAllItems = $('#" + lstBoxAllItems.ClientID + "'); var $lstBoxSelectedItems = $('#" + lstBoxSelectedItems.ClientID + "'); var $txtHiddenIDs = $('#" + txtHiddenIDs.ClientID + "'); ";
jscript += "
<script type="text/javascript" src="/_layouts/1033/EgSpi/Default/BannerEditorPart.js"></script>";
Page.ClientScript.RegisterStartupScript(typeof(string), "jscript", jscript, false);
}


Here is JQuery which do all Add/Add All/Remove/Remove All/Up/Down
$(document).ready(function () {
$lstBoxAllItems.val($('#' + $lstBoxAllItems.attr('id') + ' option:first').val())
});

$('#btnAdd').click(function () {
var options = $("#" + $lstBoxAllItems.attr('id') + ' option:selected');
options.each(function () {
$("#" + $txtHiddenIDs.attr('id') + '').val($("#" + $txtHiddenIDs.attr('id') + '').val() + ',' + $(this).val());
})

$('#' + $lstBoxAllItems.attr('id') + ' option:selected').appendTo($lstBoxSelectedItems);
$lstBoxAllItems.val($('#' + $lstBoxAllItems.attr('id') + ' option:first').val())
});

$('#btnRemove').click(function () {

var options = $("#" + $lstBoxSelectedItems.attr('id') + ' option:selected');
options.each(function () {
var idx = $("#" + $txtHiddenIDs.attr('id') + '').val().indexOf(',' + $(this).val())
$("#" + $txtHiddenIDs.attr('id') + '').val($("#" + $txtHiddenIDs.attr('id') + '').val().replace(',' + $(this).val(), ''));
})
$('#' + $lstBoxSelectedItems.attr('id') + ' option:selected').appendTo($lstBoxAllItems);
$lstBoxSelectedItems.val($('#' + $lstBoxSelectedItems.attr('id') + ' option:first').val());
});

$('#btnAddAll').click(function () {
var options = $("#" + $lstBoxAllItems.attr('id') + ' option');
options.each(function () {
$("#" + $txtHiddenIDs.attr('id') + '').val($("#" + $txtHiddenIDs.attr('id') + '').val() + ',' + $(this).val());
})

$('#' + $lstBoxAllItems.attr('id') + ' option').appendTo('#' + $lstBoxSelectedItems.attr('id') + '');
$lstBoxSelectedItems.val($('#' + $lstBoxSelectedItems.attr('id') + ' option:first').val());
});

$('#btnRemoveAll').click(function () {
$('#' + $lstBoxSelectedItems.attr('id') + ' option').appendTo('#' + $lstBoxAllItems.attr('id') + '');
$("#" + $txtHiddenIDs.attr('id') + '').val('');
$lstBoxAllItems.sort_select_box();
$lstBoxAllItems.sort_select_box();
$lstBoxAllItems.val($('#' + $lstBoxAllItems.attr('id') + ' option:first').val());
});

$('#btnMoveUp').click(function () {
$('#' + $lstBoxSelectedItems.attr('id') + ' option:selected').each(function () { $(this).insertBefore($(this).prev()) });

var options = $("#" + $lstBoxSelectedItems.attr('id') + ' option');
$("#" + $txtHiddenIDs.attr('id') + '').val('');
options.each(function () {
$("#" + $txtHiddenIDs.attr('id') + '').val($("#" + $txtHiddenIDs.attr('id') + '').val() + ',' + $(this).val());
})
});

$('#btnMoveDown').click(function () {
$('#' + $lstBoxSelectedItems.attr('id') + ' option:selected').each(function () { $(this).insertAfter($(this).next()) });

var options = $("#" + $lstBoxSelectedItems.attr('id') + ' option');
$("#" + $txtHiddenIDs.attr('id') + '').val('');
options.each(function () {
$("#" + $txtHiddenIDs.attr('id') + '').val($("#" + $txtHiddenIDs.attr('id') + '').val() + ',' + $(this).val());
})
});

$.fn.sort_select_box = function () {
$.fn.sort_select_box = function () {
var my_options = $("#" + this.attr('id') + ' option');
my_options.sort(function (a, b) {
if (a.text > b.text) return 1;
else if (a.text < b.text) return -1;
else return 0
})
$(this).empty().append(my_options);
$("#" + this.attr('id') + " option").attr('selected', false);
}
}

Monday, December 13, 2010

Opening a SharePoint Portal and Sending back form information to its parent Page

Last week I got another code challenge when I was given a task as follows:

  1. There will a be a popup which will open from Editor Part of my custom Web Part Properties
  2. User will select a user names from the list into popup and click Ok button.
  3. Now selected user names will be added into the list box control of Editor Part.

Solution:

As I had to bring the selected users from popup to parent page and parent List will be auto refreshed with the new added users.

So I kept my consolidated users details into one hidden textbox and do post back so that updated details gets refreshed in List box.

  1. Beacause we need to open SharePoint popup from Editor Part so we will have to write our popup opening javascript at runtime. As follows:
        private void GenerateJavascript()

{
string strPath = SPContext.Current.Web.Url + "/_layouts/Egspi/Default/DlgContactsSearch.aspx";
string strScript =
"function OpenDialog() { " +
"var options = SP.UI.$create_DialogOptions(); " +
"options.url = '" + strPath + "'; " +
"options.width = 360;" +
"options.height = 300; " +
"options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);" +
"SP.UI.ModalDialog.showModalDialog(options); " +
"}" +
"var messageId;" +

"function CloseCallback(result, target) { " +
"var strConsol='';" +
"if(result === SP.UI.DialogResult.OK) { " +
"var txtSearch = document.getElementById('" + txtContacts.ClientID + "');" +
"if (target != ''){" +
"var strExisting = txtSearch.value;" +
"var arrExisting = strExisting.split('#');" +
"var arrNew = target.split('#');" +
"var arrConsol = unique(arrExisting.concat(arrNew));" +
"strConsol = arrConsol.join('#');" +
"}" +
"txtSearch.value=strConsol; " +
"__doPostBack();" +
"}" +
"}" +

"function unique(arrayName) {" +
"var newArray = new Array();" +
"label: for (var i = 0; i < arrayName.length; i++) {" +
"for (var j = 0; j < newArray.length; j++) {" +
"if (newArray[j] == arrayName[i])" +
"continue label;" +
"}" +
"newArray[newArray.length] = arrayName[i];" +
"}" +
"return newArray;" +
"}" +

"function btnDeleteContacts_Click() {" +
"var strNewContacts = '';" +
"var txtSearch = document.getElementById('" + txtContacts.ClientID + "');" +
"var containerRef = document.getElementById('" + cblContacts.ClientID + "');" +
"var inputRefArray = containerRef.getElementsByTagName('input');" +
"var spanRefArray = containerRef.getElementsByTagName('span');" +
"for (var i = 0; i < inputRefArray.length; i++) {" +
"var inputRef = inputRefArray[i];" +
"if (inputRef.type.substr(0, 8) == 'checkbox') {" +
"if (inputRef.checked != true) {" +
"if (strNewContacts != '')" +
"strNewContacts += '#';" +
"strNewContacts += spanRefArray[i].getAttribute('optValue') + '~' + spanRefArray[i].getAttribute('optText');" +
"}" +
"}" +
"}" +
"txtSearch.value=strNewContacts;"+
"__doPostBack();" +
"}";

Page.ClientScript.RegisterClientScriptBlock(typeof(ContactsEditorPart), "ContactsDialogJavaScript", strScript, true);
}
 
  • OpenDialog(): This method will open our desired Popup.
options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);

check out 2nd parameter it says that this method will be called from parent when popup will get closed.


  • CloseCallback(): This method will get the selected values into target parameter as string
    Then it will check any duplicate username which is already present into Editor Part List Control, if yes then it will remove it from the target string.
    Finally it will insert target string into my hidden text box.

  • Unique(): This is simple method to remove the duplicate array elements.

  • btnDeleteContacts_Click() : There is an option to select and delete any user from Editor Part list control.

Sunday, December 12, 2010

Opening a Sharepoint Portal and Sending back form information to its parent Page

Last week I got another code challenge when I was given a task as follows:

  1. There will a be a popup which will open from Editor Part of my custom Web Part Properties
  2. User will select a user names from the list into popup and click Ok button.
  3. Now selected user names will be added into the list box control of Editor Part.
Sol:

  1. Beacause we need to open SharePoint popup from Editor Part so we will have to write our popup opening javascript at runtime. As follows:

private void GenerateJavascript() { string strPath = SPContext.Current.Web.Url + "/_layouts/Egspi/Default/DlgContactsSearch.aspx"; string strScript = "function OpenDialog() { " +
"var options = SP.UI.$create_DialogOptions(); " + "options.url = '" + strPath + "'; " + "options.width = 360;" + "options.height = 300; " + "options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);" + "SP.UI.ModalDialog.showModalDialog(options); " + "}" + "var messageId;" + "function CloseCallback(result, target) { " + "var strConsol='';" + "if(result === SP.UI.DialogResult.OK) { " + "var txtSearch = document.getElementById('" + txtContacts.ClientID + "');" + "if (target != ''){" + "var strExisting = txtSearch.value;" + "var arrExisting = strExisting.split('#');" + "var arrNew = target.split('#');" + "var arrConsol = unique(arrExisting.concat(arrNew));" + "strConsol = arrConsol.join('#');" + "}" + "txtSearch.value=strConsol; " + "__doPostBack();" + "}" + "}" + "function unique(arrayName) {" + "var newArray = new Array();" + "label: for (var i = 0; i < arrayName.length; i++) {" + "for (var j = 0; j < newArray.length; j++) {" + "if (newArray[j] == arrayName[i])" + "continue label;" + "}" + "newArray[newArray.length] = arrayName[i];" + "}" + "return newArray;" + "}" + "function btnDeleteContacts_Click() {" + "var strNewContacts = '';" + "var txtSearch = document.getElementById('" + txtContacts.ClientID + "');" + "var containerRef = document.getElementById('" + cblContacts.ClientID + "');" + "var inputRefArray = containerRef.getElementsByTagName('input');" + "var spanRefArray = containerRef.getElementsByTagName('span');" + "for (var i = 0; i < inputRefArray.length; i++) {" + "var inputRef = inputRefArray[i];" + "if (inputRef.type.substr(0, 8) == 'checkbox') {" + "if (inputRef.checked != true) {" + "if (strNewContacts != '')" + "strNewContacts += '#';" + "strNewContacts += spanRefArray[i].getAttribute('optValue') + '~' + spanRefArray[i].getAttribute('optText');" + "}" + "}" + "}" + "txtSearch.value=strNewContacts;"+ "__doPostBack();" + "}"; Page.ClientScript.RegisterClientScriptBlock(typeof(ContactsEditorPart), "ContactsDialogJavaScript", strScript, true); }

  • OpenDialog(): This method will open our desired Popup.
options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);

check out 2nd parameter it says that this method will be called from parent when popup will get closed.

  • CloseCallback: This method will get the selected values into target parameter as string

    Then it will check any duplicate username which is already present into Editor Part List Control, if yes then it will remove it from the target string.

    Finally it will insert target string into my hidden text box.

  • unique: This is simple method to remove the duplicate array elements.

  • btnDeleteContacts_Click() : There is an option to select and delete any user from Editor Part list control.


Monday, December 6, 2010

Security trimming on CustomActions tag for custom menu items and ribbon buttons

We often need to add a security trimming for our custom menu items or ribbon buttons using CustomActions tag.

Here is the solution

<customaction
ContentTypeId = "Text"
ControlAssembly = "Text"
ControlClass = "Text"
ControlSrc = "Text"
Description = "Text"
GroupId = "Text"
...
Rights = "Text"
..>

We can apply security trimming using 'Rights' attribute.

There are lot of options that can be used as value for this attribute.

Check out this link to see possible values


Happy Sharepointing :)

Monday, November 8, 2010

"BDC Metadata Store is currently unavailable" when I try to get the External Content Types on SPD

This issue I faced when I was trying to make one POC using BCS for SharePoint 2010.

First I found that my SP was trial so I upgraded it to "SharePoint Server with Enterprise Client Access License".

I was giving me same error even after upgrading then i saw on other vpc with same config and licence where it was working.

There I found the solution, which is that we need to do association of BDC service with the desired web application.

Goto : Central Admin -> Application Mgt -> Manage Web Application -> Select desired Web Application -> click 'Service Connections' from ribbon buttons -> in the popup make sure "Business Data Connectivity Service" is checked.

And bingo it worked..

Wednesday, October 20, 2010

Populate list items automatically when list definition feature gets activated

SharePoint 2010 - There was a requirement in which I had to populate 2 list items when its list definition feature gets activated.

Following is the solution:

Into Elements.xml file of list instance


< ?xml version="1.0" encoding="utf-8"?>

< Elements xmlns="http://schemas.microsoft.com/sharepoint/">

< ListInstance Title=....... ;">



< Data>

< Rows>

< Row>

< Field Name="Title">.....</Field>

< Field Name="MailBody">.....</Field>

< /Row>

< Row>

< Field Name="Title">.....</Field>

< Field Name="MailBody"></Field>

< /Row>

< /Rows>

< /Data>



< /ListInstance>

< /Elements>

Happy SharePointing.... :)

Validate CheckboxList Control with javascript to make sure atleast one checkbox is checked

While developing one page which sends mail to the selected group from the checkbox list I got requirement to impose validation to check atleast one group should be selected.

Here is the solution.....

< id="CvalGroupCheckbox" display="Dynamic" runat="server" cssclass="MsgLabel" errormessage="" clientvalidationfunction="validateGroupSelection">

< language="javascript" type="text/javascript">

function validateGroupSelection(source, arguments) {
document.getElementById("").style.visibility = "hidden";
var chkSubUsers = document.getElementById('_0');
var chkTestUsers = document.getElementById('_1');

if ((!chkSubUsers.checked) && (!chkTestUsers.checked))
arguments.IsValid = false;
else
arguments.IsValid = true;
}

< /script>

Happy programming.... :)