Thursday, 27 February 2014

Elements appear when mouse hovers above them - CSS and jQuery

I'm going to share that with you, because it took me surprisingly long time to figure out.

I wanted to have an element, that shows up only, when mouse moves over the element. Just like this:
My first idea was to use "hide()" and "show()" methods on elements themselves. Unfortunately, when elements were hidden, they had no size (or actually size was 0), so you could not hover over them to show them.

Second idea, was to use CSS, and change visibility in ":hover" style. That worked partially - the <div> element had <i> child. Only child would be visible (after all, it's cascading style sheets, it does not go up).

My final idea, was to contain my elements in larger <div> element. The DIV has fixed size and position, and display: block. Child elements are initially hidden. Then I bind "hover()" event to the parent div, that finds children, and displays them. And then hides, when mouse leaves.

So, this is the markup:
<div class="show">
    <div class="mouseover"><i class="fa fa-something"></i></div>
    <div class="mouseover"><i class="fa fa-something-else"></i> </div>
</div>

And this is the script:
$(function(){
    $('.show').hover(
    function() {
        $(this).find('.mouseover').fadeIn();
    },
    function() {
        $(this).find('.mouseover').fadeOut();
    });
});

Monday, 24 February 2014

Web.config changing when publishing application - how to avoid it?

I have MVC website, that I deployed to Azure. The application uses EF Code First. 

After deployment, these lines were added to web.config:

  <connectionStrings>
    <add name="LoremIpsum.LoremContext" 
         connectionString="LoremIpsum.LoremContext_ConnectionString" 
         providerName="System.Data.SqlClient" />
  </connectionStrings>

This caused this error:

Format of the initialization string does not conform to specification starting at index 0.

I solved this by going to my Publish Profile (the .pubxml file) and deleted following lines:

  <ItemGroup>
    <MSDeployParameterValue Include="$(DeployParameterPrefix)LoremIpsum.LoremContext-Web.config Connection String">
      <ParameterValue>... my actual connection string ...</ParameterValue>
    </MSDeployParameterValue>
  </ItemGroup>
  <ItemGroup>
    <_ConnectionStringsToInsert Include="LoremIpsum.LoremContext" />
  </ItemGroup>

Monday, 25 November 2013

Don't use SPList.Items, use GetItems() instead

private static void GetItemsFromList()
{
    //from MDSN: It is best practice is to use one of the GetItem* methods of SPList to return a filtered collection of items.

    using (SPSite site = new SPSite(webUrl))
    {
        using (SPWeb web = site.OpenWeb())
        {
            SPList list = web.GetList(ListUrl);  //my list has 2 items
            Console.WriteLine(list.ItemCount);   //returns 2
            Console.WriteLine(list.Items.Count); //returns 0

            foreach (SPListItem item in list.Items)
            {
                // will not go inside loop, because list.Items is empty
            }

            for (int i = 0; i < list.ItemCount; i++)
            {
                var item = list.Items[i];  //will cause ArgumentOutOfRangeException
            }

            var items = list.GetItems(new SPQuery());  //returns all items
        }
    }
}

Wednesday, 11 September 2013

Crystal Reports: word wrap

How to make long text in field wrap automatically? (some screenshots in German)

Right-click on field -> Format Object

In General tab select variable size

And make field tall enough to fit more than one line of text

Monday, 12 August 2013

Local Security Authority problem

Ever tried to log in to your remote computer, only to see this error message?
An authentication error has occurred. The Local Security Authority cannot be contacted.

I have my Azure Virtual Machine configured in domain. The Domain Controller and DNS is also an Azure VM. I'm trying to log in with my domain credentials. This error means, that the remote machine cannot access domain controller.
This error often occurs (or rather always and only) after I restarted VM - e.g. to change number of cores or memory.

Solution:

1. Log in to VM using local user, not domain one.
2. Open network and sharing center.
3. Click "Change adapter settings". As you can see, Windows cannot identify your domain.
4. Right-click network card icon, open Properties, double-click "Internet Protocol Version 4".
5. DNS server address disappeared. Set it again.
6. Now, you're back in domain. Log out and log in with domain credentials.

Wednesday, 7 August 2013

VPN broke my SharePoint

When I navigated to my SharePoint site, I saw this message:
This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products Configuration Wizard, located on the Start menu in Microsoft SharePoint 2010 Products.
The reason for this was, I installed Cisco VPN on my server in order to be able to access internal network and work with TFS (in 192.168.x.x range).
Unfortunately, SQL Server is on another private network (10.x.x.x range). And as result, it could not be found by SharePoint server.

Disconnecting from VPN solved my problem.

Tuesday, 6 August 2013

Always run Visual Studio as administrator

Here I will show how to set Visual Studio to always run as administrator under Windows Server 2012 or Windows 8.

1. Pin VS to taskbar
2. Right click on VS icon

3. Right click on Visual Studio 2012

4.  Select Properties. Go to Compatibility
5.  Select "Run this program as an administrator".


Monday, 29 July 2013

SharePoint social feed - how to get mentions

The article on MSDN is good starting point [1]. It shows example on how to get feed manager, make asynchronous call and retrieve newsfeed.

Instead of retrieving newsfeed, let's retrieve mentions. For this use getMentions() method[2].

In original code, while iterating, all non-normal threads were ignored. Here instead, only thread type 3 will be used [3].
Original code retrieved Text property from Thread [4]. For mentions, that would always render something like "Mentioned by John Doe". We need to go deeper in thread's properties to get actual mention text. See code example below.

Another challenge is to get URL of story. I could not find this in documentation, but was able to reverse engineer this property from raw object.
var url = thread.$2c_1;
In the end, text and url were pushed into array, so I can work with it in later and display for user in any form that is convenient.
        var mentionsArray = [];
        var mentionsCount;
        // Ensure that the SP.UserProfiles.js file is loaded before the custom code runs.
        SP.SOD.executeOrDelayUntilScriptLoaded(GetFeeds, 'SP.UserProfiles.js');

        // Declare global variables.
        var clientContext;
        var feedManager;
        var mentionsFeed;

        function GetFeeds() {

            // Initialize the current client context and the SocialFeedManager instance.
            clientContext = SP.ClientContext.get_current();
            feedManager = new SP.Social.SocialFeedManager(clientContext);

            // Set parameters for the feed content that you want to retrieve.
            var feedOptions = new SP.Social.SocialFeedOptions();
            feedOptions.set_maxThreadCount(10); // default is 20

            // Change the sort order to optimize the Timeline feed results.
            feedOptions.set_sortOrder(SP.Social.SocialFeedSortOrder.byCreatedTime);
            mentionsFeed = feedManager.getMentions(false, feedOptions);     //do not clear unread mentions

            clientContext.load(feedManager);
            clientContext.executeQueryAsync(CallIterateFunctionForFeeds, RequestFailed);
        }
       function CallIterateFunctionForFeeds() {
            IterateThroughFeed(mentionsFeed);

            // Later mentionsArray will be boud by using Knockout.js ;)
            var viewModel = new AppViewModel();
            ko.applyBindings(viewModel);
        }
        function IterateThroughFeed(feed) {
            var feedOwner = feedManager.get_owner().get_name();

            // Iterate through the array of threads in the feed.
            var threads = feed.get_threads();
            mentionsCount = feed.get_unreadMentionCount();

            for (var i = 0; i < threads.length ; i++) {
                var thread = threads[i];
                var actors = thread.get_actors();

                // Use mentions. (SocialThreadType.mentionReference)
                if (thread.get_threadType() == 3) {

                    // Get the root post's author, content, and number of replies.
                    var post = thread.get_rootPost();
                    var authorName = actors[post.get_authorIndex()].get_name();
                    var postContent = post.get_text();
                    var postReference = thread.get_postReference();
                    var referencedPost = postReference.get_post();
                    var mentionText = referencedPost.get_text();

                    var url = thread.$2c_1;         //reverse engineered this name

                    mentionsArray.push({ text: postContent + " " + mentionText, url: url });
                }
            }
        }
        function RequestFailed(sender, args) {
            //not implemented
        }
MSDN Articles:
[1] Retrieve social feeds by using the SharePoint 2013 JavaScript object model http://msdn.microsoft.com/en-us/library/jj164025.aspx#bkmk_GetFeeds
[2] SP.Social.SocialFeedManager.getMentions Method http://msdn.microsoft.com/en-us/library/jj679814.aspx

Monday, 8 July 2013

Creating SharePoint 2013 on Azure VMs - checklist

Follow this checklist to create SharePoint 2013 Server with configuration database on separate Virtual Machine.
  1. Create Network in Azure
  2. After that create two VMs - first with SQL, second with SP
  3. During creating, add them both to the same Network
  4. Log into first VM - the SQL one. Add AD DS feature and promote it to domain controller
  5. Create domain user, that will be SP SQL user.
  6. Open SQL Management Studio and create login and permissions for SP SQL user
  7. Open Windows Firewall and set inbound rule for port 1433 (SQL Server)
  8. Go to Azure and create endpoint for first VM for port 1433
  9. Log into second VM - the SP one. Join it to domain.
  10. Start SP Configuration Wizard, Create new server farm, use SP SQL user to create configuration DB, configure the rest