Fix selected tab in SharePoint top links menu

Fastest way to accomplish this is to use jquery! 🙂

function fixTabs(){
    $.each($(".customNavTabActive"), function() {
        $(this).removeClass("customNavTabActive");
        $(this).parentsUntil("table").each(function() {
            $(this).removeClass("customNavTabActive");
        });
    });
    $.each($("a.customNavTab"), function() {
        if (this.href == document.location.href || this.href + "/default.aspx" == document.location.href) {
            $(this).parent("td").addClass("customNavTabActive");
        }
    });
}

Update: I have improved this code a little bit 🙂

function fixTabs(){
    var normalNavTavCss = "customNavTab";
    var firstCellActiveCss = "customNavTabActive";
    var firstCellCss = "customNavTab";
    var lastCellActiveCss = "customNavTabActive";
    var lastCellCss = "customNavTab";
    var cellActiveCss = "customNavTabActive";
    $.each($("." + cellActiveCss), function() {
        $(this).removeClass(cellActiveCss);
        $(this).parentsUntil("table").each(function() {
        $(this).removeClass(cellActiveCss);
        });
    });
    var lastCell;
    var lastCellSelected;
    $.each($("." + normalNavTavCss + " a"), function(i) {
        lastCell = $(this).parent("td");
        var location = document.location.href.replace("/default.aspx", "");
        var link = this.href.replace("/default.aspx", "");
        lastCellSelected = (link == location || location.indexOf(link) > -1);
        if (lastCellSelected) {
            if (i == 0) {
                lastCell.addClass(firstCellActiveCss);
            }
            else {
                lastCell.addClass(cellActiveCss);
            }
        }
        else if (i == 0) {
            lastCell.addClass(firstCellCss);
        }
    });
    if (lastCellSelected) {
        lastCell.removeClass(cellActiveCss);
        lastCell.removeClass(firstCellActiveCss);
        lastCell.addClass(lastCellActiveCss);
    }
    else {
        lastCell.addClass(lastCellCss);
    }
}

Most common used xlt transformations on web.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<connectionstrings>
        <remove name="MyEntities" xdt:Transform="InsertBefore(/configuration/connectionStrings/add)"/>
        <add name="MyEntities" 
             connectionString="yourconnstring" 
             providerName="System.Data.EntityClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
        <remove name="MyEntities2" xdt:Transform="InsertBefore(/configuration/connectionStrings/add)"/>
        <add name="MyEntities2"
             connectionString="yourconnstring"
             providerName="System.Data.EntityClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
        <add name="ApplicationServices" connectionString="" xdt:Transform="Remove"/>
</connectionstrings>
 
<system .web>
<trust level="Full" xdt:Transform="InsertBefore(/configuration/system.web/compilation)" />
<authorization xdt:Transform="InsertBefore(/configuration/system.web/authentication)">
<allow roles="Administrator"/>
<deny users="*"/>
</authorization>
<authentication xdt:Transform="Remove"></authentication>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<membership xdt:Transform="Remove"></membership>
<rolemanager xdt:Transform="Remove"></rolemanager>
<profile xdt:Transform="Remove"></profile>
<!--
In the example below, the "Replace" transform will replace the entire
<customErrors> section of your web.config file.
Note that because there is only one customErrors section under the
</system><system .web> node, there is no need to use the "xdt:Locator" attribute.
<customerrors defaultRedirect="GenericError.htm"
mode="RemoteOnly" xdt:Transform="Replace">
<error statusCode="500" redirect="InternalError.htm"/>
</customerrors>
-->
</system>

I have some problems with saving and to WordPress post, so dont just copypaste this snippet.

IIS and ASP.NET 4.0 applications

If you cannot start debugging on web server, cannot open application on IIS at all, have any problems with managed integrated handler or similar when accessing application, then you need to install .NET 4.0 on server. Easiest way is using Web Platform Installer, under Frameworks.

If .NET 4.0 is already installed, then you need to open cmd as Administrator, and run “%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i”

That solved problems for me.

Sir sa jajima i sirom

Ovo je jedno jelo koje moram da opišem. Sve je počelo tako što sam bio sam u stanu, i gladan. Došao sam do frižidera da vidim šta ima unutra, i nađem svježi sir zbregov – zadnji dan roka, a neotvoren. Uključim šporet, uzmem 2 jaja, razbijem ih i izmutim sa malo mlijeka i dodam malo brašna. To saspem u veliku tavu za palačinke, i kad se malo počelo stvrdnjavati, bacim na to onih pola kile sira jer ne mogu ostaviti ništa – propade 🙂
Odmah se vidjelo da je tava za palačinke greška za ovaj poduhvat pa sam uzeo veliku tavu i pretresao sve u nju, i izmiješao onaj omlet sa dna u sir. Potom se ta smjesa od temperature razrijedila, i sir se pretvorio u tekućinu. U to sam usuo još jedno jaje, malo posolio i izmiješao pa je dobilo žućkastu boju. Miješajući “to” sam shvatio da se tako ne može jesti jer to nije nikakvo jelo, ni supa, nije ništa. Onda sam uzeo dvije kriške hljeba i udrobio u to, i izmiješao, i onda je počelo da liči na neku žućkastu poparu, ili bijelu cicvaru, hljeb se baš lijepo povezao s tim i zgusnuo smjesu, ali je još bila pomalo tečna, a nisam htio da stavljam više hljeba jer bi bilo previše, ostali bi komadići neistopljenog hljeba, pa sam našao 3 lista gauda sira, koja sam smotao u rolu i isjeckao u tu smješu, a onda izmiješao dok se nije istopio i povezao sa ostatkom.
Tada sam tavu sklonio sa šporeta i stavio da se hladi, a dok sam čekao, iskidao sam u to nekoliko listova kulena, i isjeckao unutra 5 maslina, i sve smiješao.
Rezultat je bio mimo svih mojih očekivanja. Ovo je jedno izvanredno jelo, ali obavezno u njega treba ići neki kulen koji dobro miriše. Smjesa sireva i hljeba je upila sav taj miris i aromu, i ukus je toliko fantastičan koliko je izgled očajan:

Localizing Sharepoint resources – transliteration to Cyrillic

Recently I tried to localize MS WSS 3.0 site collection to unsupported language – Serbian, cyrillic (Serbia). LCID of this culture is 3098. This language is almost the same as existing latin localization to Serbian (Serbia) with LCID 2074. To get cyrillic version of resource files (resx), I installed Serbian latin language pack and searched wwwroot and 12 folders for “sr-latn-cs”, and took following files: core.sr-latn-cs.resx, resources.sr-latn-cs.resx, spadmin.sr-latn-cs.resx, spcore.sr-latn-cs.resx, spsearchadmin.sr-latn-cs.resx and wss.sr-latn-cs.resx

I got Search Center and language pack for it installed, so in an environment without search center, there should be some of these files missing.

To get sr-cyrl-cs.resx versions of theese files, I made small console application which parsed through xml files and replaced latin letters with cyrillic. Character swap is simple, and to parse xml I used following code:

static void Main(string[] args)
        {
            if (args.Length == 0) args = new string[]{"source", "destination"};
            DirectoryInfo source = new DirectoryInfo(args[0]);
            foreach (FileInfo file in source.EnumerateFiles())
            {
                XmlTextReader reader = new XmlTextReader(file.OpenText());
                XmlDocument doc = new XmlDocument();
                doc.Load(reader);
                reader.Close();
                FileInfo dest = file.CopyTo(Path.Combine(args[1], file.Name.Replace(SourceLang, DestLang)), true);
                XmlDocument destination = new XmlDocument();
                foreach (XmlNode node in doc.ChildNodes)
                {
                    ParseChildren(node);
                }
 
                XmlTextWriter writer = new XmlTextWriter(dest.OpenWrite(), Encoding.Unicode);
                doc.Save(writer);
                writer.Close();
            }
        }
 
        private static void ParseChildren(XmlNode sourceNode)
        {
            foreach (XmlNode node in sourceNode.ChildNodes)
            {
                switch (node.NodeType)
                {
                    case XmlNodeType.Text:
                        if (node.Name == "#text" && node.HasChildNodes == false 
                            && node.Value.Length > 0 && node.ParentNode.ParentNode.Name == "data")
                        {
                            if (!node.ParentNode.ParentNode.Attributes["name"].Value.ToUpper().Contains("accesskey".ToUpper())
                                && !node.ParentNode.ParentNode.Attributes["name"].Value.ToUpper().Contains("_AK".ToUpper()))
                            {
                                node.Value = SmartConvertToCyrillic(node.Value);
                            }
                            else
                            {
                                break;
                            }
                        }
                        break;
                    default:
                        break;
                }
                if (node.HasChildNodes)
                    ParseChildren(node);
            }
        }

Important lines here are in case XmlNodeType.Text:

Those lines discriminate nodes which are values and need to be transliterated to Cyrillic.

When new resx files have been placed back to same respective folders where their sources for transliteration were found, then new language had to be enabled in Sharepoint.

Registry key HKEY_LOCAL_MACHINESOFTWAREMicrosoftShared ToolsWeb Server Extensions12.0InstalledLanguages contains string values whose names are LCID-s of installed languages, and value is version of satellite assembly of microsoft.sharepoint.intl.resources.dll in GAC. I added new string value named “3098” with value “12.0.0.0”. I even disassembled latin version of this dll and made cyrillic but I have what it seems unsolvable problem of impossibility to build that dll in Language version other than “Language neutral”, and I believe that is the key to enable localization of administration pages and parts of UI that is not localized.

Adding 3098 registry value enabled “Serbian Cyrillic” language in “New Web Site” SharePoint page, but to get templates for Team site, Blank, etc, it is necessary to make “3098” folder in C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATE

I used 2074 folder as a template, and edited files in 2074/XML subfolder to get site templates in site creation wizard.

Newly created site was mostly localized – parts which are visible to users, but administrative pages are localized from satellite dll, and I did not succeed in building language specific version of dll to use it for this purpose. Also, this dll must be signed for SharePoint to use it, and to circumvent this I used delay sign, and then added exception for signature verification using gacutil.

This was very useful resource http://social.msdn.microsoft.com/Forums/en/sharepointdevelopmentprerelease/thread/023d1fb9-c415-405a-8944-c709c0cc8f01