Category Archives: Style Sheets

How to Create a Dictionary in SharePoint

Overview
This tutorial will help you build a dictionary in SharePoint using an auto suggest feature that calls up terms from the centralized term store.
No server side web part development; everything in this article to create the dictionary was developed using JavaScript, SPServices, CSS and a custom list. Using the SharePoint Client Object Model would be a better choice for this type of project and has extensive capabilities of making your site more dynamic and functional.

Using SPServies
SPServices is a JQuery library abstract SharePoint web services and make them easy to use it. If you have not worked with SPServices,
check out the website for more detailed information about its functionality. It works entirely client side and requires no server install.

Download the jquery files from the site and upload them to your SharePoint server. For this project, I placed the files under the Site Assets directory so they could be accessed anywhere in the Site Collection.

Getting Started
Starting with HTML and some CSS, I created a web page similar to the image below. If a user clicks on a letter, all the terms and definitions starting with that letter will appear below inside a div element. Note that there are a few linked Javscript and external CSS files including the main jquery library, SPServices.js, and the autosuggest jquery files. Dictionary.js and dictionary_autosuggest.js are two Javascript files that contain the client side functionality of the search features. More details are explained later in this article.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>

<title>TS Dictionary</title>

<script type="text/javascript" src="/style%20library/services-plugin/js/jquery.js"></script>

<!-- autocomplete files -->

<link href="/Site Assets/jquery-ui-1.10.0.custom.css" rel="stylesheet"/>

<script src="/Site Assets/jquery-ui-1.10.3.custom.min.js"></script>

<script src="/Site Assets/jquery.SPServices-0.7.2.min.js" language="javascript" type="text/javascript"></script>

<script type="text/javascript" src="/site Assets/dictionary.js"></script>

<script type="text/javascript" src="/site Assets/dictionary_autoSuggest.js"></script>

<style type="text/css">

#author_alphabetic {
text-align:center;
}
#author_alphabetic ul {
}

#author_alphabetic li {
float:left;
margin:2px 2px 0 0;
}

#author_alphabetic a {
background-color:#3d7fac;
position:relative;
width:40px;
height:40px;
border:1px solid rgb(61, 127, 172);
text-decoration:none;
font-size:22px;
font-weight:bold;
font-family: "Verdana";
float:left;
display:inline;
color:white;
line-height:2.0;
}

#author_alphabetic a span {

/* background:url(../image/alpha_br.png) no-repeat right bottom; */
width:75px;
height:75px;
display:block;
position:absolute;
top:-2px;
left:-8px;
}

#author_alphabetic a:hover {
background:rgb(61, 127, 172);
z-index:100;
}

#author_alphabetic a:hover span.first {
display:block;
font-size:22px;
line-height:2.0;
font-weight:bold;
color:white;
cursor:pointer;
width:40px;
height:40px;
top:-1px;
left:-1px;
background:rgb(119, 165, 197);
border:1px solid rgb(255, 255, 255);
}

#author_alphabetic a:hover span span {
display:block;
position:relative;
left:1px;
top:-4px;
width:41px;
height:41px;
}

.ui-autocomplete {
max-height: 400px;
overflow-y: auto;
/* prevent horizontal scrollbar */
overflow-x: hidden;
}

/* IE 6 doesn't support max-height * we use height instead, but this forces the menu to always be this tall */*
html .ui-autocomplete {
height: 100px;
}
.myInput {
position:relative;
left:40px;
width:300px;
border:0px;
max-width:240px;
height:42px ;
background: url("/style%20library/enetThemeimages/input6.png") 0 0 ;
background-repeat: no-repeat;
line-height:32px;
padding-left:5px;
font-family:"Arial",Georgia,Serif;
color: #8a8484;
font-size:14px;
size:250px;
padding-right: 5px;
top:-20px;
}

.myButton{
position:relative;
left:45px;
background: no-repeat url("/style%20library/enetThemeimages/searchbutton.png") 0 0 ;
width:97px;
height:42px;
border:0px;
cursor:pointer;
top:-20px;
}
</style>

<body>
<h3 style="padding-left:105px;padding-top:-30px; position:relative;top:30px; width:470px; color:#787878">Click search or use the enter key to call up a dictionary term. </h3>
<div style="position:relative; top:-20px; left:4px; background-color:transparent; width:100px; height:80px">
<img src="/style%20library/enetThemeImages/glass.png" />
<div style="background-color:transparent; width:500px; height:100px;position:relative; left:110px;">
<table border=0><tr><td>
<input type="text" id="txtSearch" class="myInput" value="Search the dictionary..." onClick="clearMe()" onkeypress="searchKeyPress(event);" />
</td><td>
<input type="button" id="btnSearch" value="" onclick="getTerm();" class='myButton' /> </td>
</table>
</div>
</div>
<div id="author_alphabetic" style="position:relative; top:10px; left:-14px">
<ul>
<li><a href="#" onclick="getVals('A')" title="A"><span class="first"><span>A</span></span></a></li>
<li><a href="#" onclick="getVals('B')" title="B"><span class="first"><span>B</span></span></a></li>
<li><a href="#" onclick="getVals('C')" title="C"><span class="first"><span>C</span></span></a></li>
<li><a href="#" onclick="getVals('D')" title="D"><span class="first"><span>D</span></span></a></li>
<li><a href="#" onclick="getVals('E')" title="E"><span class="first"><span>E</span></span></a></li>
<li><a href="#" onclick="getVals('F')" title="F"><span class="first"><span>F</span></span></a></li>
<li><a href="#" onclick="getVals('G')" title="G"><span class="first"><span>G</span></span></a></li>
<li><a href="#" onclick="getVals('H')" title="H"><span class="first"><span>H</span></span></a></li>
<li><a href="#" onclick="getVals('I')" title="I"><span class="first"><span>I</span></span></a></li>
<li><a href="#" onclick="getVals('J')" title="J"><span class="first"><span>J</span></span></a></li>
<li><a href="#" onclick="getVals('K')" title="K"><span class="first"><span>K</span></span></a></li>
<li><a href="#" onclick="getVals('L')" title="L"><span class="first"><span>L</span></span></a></li>
<li><a href="#" onclick="getVals('M')" title="M"><span class="first"><span>M</span></span></a></li>
<br><br><br><br><br>
<li><a href="#" onclick="getVals('N')" title="N"><span class="first"><span>N</span></span></a></li>
<li><a href="#" onclick="getVals('O')" title="O"><span class="first"><span>O</span></span></a></li>
<li><a href="#" onclick="getVals('P')" title="P"><span class="first"><span>P</span></span></a></li>
<li><a href="#" onclick="getVals('Q')" title="Q"><span class="first"><span>Q</span></span></a></li>
<li><a href="#" onclick="getVals('R')" title="R"><span class="first"><span>R</span></span></a></li>
<li><a href="#" onclick="getVals('S')" title="S"><span class="first"><span>S</span></span></a></li>
<li><a href="#" onclick="getVals('T')" title="T"><span class="first"><span>T</span></span></a></li>
<li><a href="#" onclick="getVals('U')" title="U"><span class="first"><span>U</span></span></a></li>
<li><a href="#" onclick="getVals('V')" title="V"><span class="first"><span>V</span></span></a></li>
<li><a href="#" onclick="getVals('W')" title="W"><span class="first"><span>W</span></span></a></li>
<li><a href="#" onclick="getVals('X')" title="X"><span class="first"><span>X</span></span></a></li>
<li><a href="#" onclick="getVals('Y')" title="Y"><span class="first"><span>Y</span></span></a></li>
<li><a href="#" onclick="getVals('Z')" title="Z"><span class="first"><span>Z</span></span></a></li>
</ul></div>
<span style=" line-height:32px"> <a href="#" onclick="getAllVals()" title="Show All" align="absmiddle">Show All</a> </span>
<br /><br><br><br><br><br>
<div id="MainDiv" style="background-color:transparent; padding-left:40px; ">
<div id="ShowMeTerm" style="background-color:transparent; font-size:12px; color:blue; width:700px" valign="top"></div
<div id="ShowMeDef" ></div></div></body></html>

Create Dictionary List

After the htm file was uploaded to the WFE, I created a custom list named ‘Dictionary’ and added a column called ‘Definition’ with a type of multilines of text. I used the Title column as the term to define. Added a few list items so content could be available for testing.

Create Term-Set

On the top level site of the site collection, go to Site Actions > Site Settings and under Site Administration click on > Term store management. On the left pane in the Taxonomy term store create a new term-set called ‘Dictionary.’ Give it a description and allow the submission policy be checked as Open. Add the same terms as you did in the custom list. Save changes.

Go back to the Dictionary list settings to add a new metadata column called ‘MetaData.’ In the term-set settings tree-view, select the Dictionary term-set to link the metadata to the term-set.

Once this is completed, a new field in the form called ‘MetaData’ will be added. Create a new .aspx page on your site where you created the Dictionary custom list. Add the Dictionary custom list to the page and publish. When you click ‘Add new item’, you can manually add new terms and definitions to the list. At this point, you have a SharePoint page that displays an input field a search button and A-Z boxes. Notice a div entitled ‘ShowMeTerm. ’ This is where the definitions will be displayed dynamically on the page.

Binding the AutoSuggest Feature to the input field

In the Javscript below, it starts off with variable declarations. As the function getKeywords gets initiated, the script is calling SharePoint client object model and begins to load term-set from the metadata columns “TSDictionary” that you created earlier. If the term-set is correctly found, then the function OnLoadSuccess is processed followed by two more functions; GetTermsRecursive and getVals(‘A’).

GetTermsRecursive calls the SPServices Jquery script which then queries the term-set. GetData function gathers all the data in the term-set into an array (“mySortedArry”) and then becomes binded to the input field “txtSearch.”

mySortedArry = myListTerms.split(",");
var myListTerms2 = String(mySortedArry);
$("#txtSearch").autocomplete({ source: myListTerms2.split(",")

The getVals() function is initiated when a user clicks on any of the A-Z letters. This function uses a CAML to query the Dictionary custom list and select all the terms and definitions that start with the letter in the variable letter. For example, getVals(‘G’) will display all the terms beginning with G.

<View><Query><Where><BeginsWith><FieldRef Name=’Title’/>’ + ‘<Value Type=’Text’>’ + letter + ‘</Value></BeginsWith></Where><OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy></Query></View>

The function onQuerySucceeded() gets called to display the results of the CAML query inside the “ShowMeTerm” div by using innerHTML.

In a similar manner, the Show All link will call up the getAllVals() function and by using another CAML query, will

display every result returned from the Dictionary list.

Dictionary_autosuggest.js



JSRequest.EnsureSetup();

    var myGlobalSearch ;
    var clientContext;
    var oList;
    var camlQuery;
    var listItemInfo = '';
    var listItemInfo2 = '';
    var listItemEnumerator;
    var termPresent;
    var srchTerm;
    var myListTerms= '';
    var TaxTerms = {
        termId: "",
        termName: "",
        child: null
    }

 

    //---------init  begin taxonomy ----------------->

    var TaxConfiguration = {
        SspId: "",
        GroupId: "",
        TermSetId: "",
        Configuration: "",
        ParseConfiguration: function () {

 

            xmlDoc = $.parseXML(this.Configuration);
            xml = $(xmlDoc);
            var properties = xml.find("Property");

            for (i = 0; i < properties.length; i++) {
            propertyName = properties[i].firstChild.textContent == undefined ?
            properties[i].firstChild.text : properties[i].firstChild.textContent;
            propertyValue = properties[i].lastChild.textContent == undefined ?
            properties[i].lastChild.text : properties[i].lastChild.textContent;
               if (propertyName == propertyValue) {
                    propertyValue = "";
                }

 

                switch (propertyName) {
                    case "SspId":
                        this.SspId = propertyValue;
                        break;
                    case "GroupId":
                        this.GroupId = propertyValue;
                        break;
                    case "TermSetId":
                        this.TermSetId = propertyValue;
                        break;
                }
            }
        }
    }

 

    // goes to this function

    function GetTermsRecursive(sspId, termSetId, myListTerms) {   
        var terms = new Array();
        var returnValue;
        $().SPServices({
            operation: "GetChildTermsInTermSet",
            sspId: sspId,
            termSetId: termSetId,
            lcid: 1033,
            completefunc: GetData
        });
    }


    function GetChildTermsRecursive(sspId, termSetId, roottermId) {
        var terms = new Array();
        $().SPServices({
            operation: "GetChildTermsInTerm",
            sspId: sspId,
            termId: roottermId,
            termSetId: termSetId,
            lcid: 1033,
            completefunc: GetData
        });
       return myListTerms;

    }

 
    function GetData(xData, Status) {
        if (Status == "success") {
            terms = new Array();
            xmlData = xData;
            // Fix for different XML parsing in IE and Chrome
            termsContent = $.parseXML(xmlData.responseText).firstChild.textContent == undefined ?
            $.parseXML(xmlData.responseText).text :
            $.parseXML(xmlData.responseText).firstChild.textContent;
            termsXML = $.parseXML(termsContent);
            $termsXML = $(termsXML);
            childTerms = $termsXML.find("T");
            parentTermId = null;
            filterOutput = "<ul>";
            for (i = 0; i < childTerms.length; i++) {
                termName = $(childTerms[i]).find("TL");

                hasChildTermsXml = $(childTerms[i]).find("TM");
                // request if child terms are avaliable

                hasChildTerms = $(hasChildTermsXml).attr("a69");
                var tsTerm = new Object();
                // Requesting actual term id
                tsTerm.termId = $(childTerms[i]).attr("a9");
                // Requesting term name

                tsTerm.termName = termName.attr("a32");

                // Setting Parent Term ID

                parentTermId = $(hasChildTermsXml).attr("a25");
                filterOutput += "<li id='" + tsTerm.termId + "'>" + tsTerm.termName;
                // try to put termName in doug comma delimited array - this works!!
                myListTerms+= ',' + tsTerm.termName;
                 // for debugging puroposes
                // If child terms are avaliable query child terms
                if (hasChildTerms != undefined && hasChildTerms == "true") {
                    // Request child Terms
                    tsTerm.child = GetChildTermsRecursive(taxconfig.SspId, taxconfig.TermSetId, tsTerm.termId);
                    tsTerm.hasChildTerms = true;
                } else {
                    tsTerm.child = null;
                    tsTerm.hasChildTerms = false;
                }

                filterOutput += "</li>";
                terms[i] = tsTerm;
            }
            filterOutput += "</ul>";
            // If parent element is specified query for parent element
            if (parentTermId != undefined || parentTermId != null) {
                $("#" + parentTermId).append(filterOutput);
            } else {
                currentFilter = $("#filter").html();
                $("#filter").html(currentFilter + filterOutput);

            }
            //  sort comma delimited string
             mySortedArry = myListTerms.split(",");
             var myListTerms2 = String(mySortedArry);                                                    
              $("#txtSearch").autocomplete({ source: myListTerms2.split(",")

            });
       
            //return dictionaryTerms;

        }

    }


    var fieldCollection;
    var termField = null;
    var termSetTerms = Array();
    var taxconfig = TaxConfiguration;
 

    function OnLoadFailed(sender, args) {
        alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());

    }
 
    //------ end taxonomy code------------------------------//
    $(document).ready(function () {
                ExecuteOrDelayUntilScriptLoaded(getKeywords, "sp.js");
                clearFormData() ;    
    });


    function getKeywords() {
        var clientContext = SP.ClientContext.get_current();
        if (clientContext != undefined && clientContext != null) {
            var webSite = clientContext.get_site().get_rootWeb();
            // Select 'Action' Field
            fieldCollection = webSite.get_fields();
            this.termField = fieldCollection.getByInternalNameOrTitle("TSDictionary");
            // Load Context
            clientContext.load(this.fieldCollection);
            clientContext.load(this.termField);
            clientContext.executeQueryAsync(Function.createDelegate(this, this.OnLoadSuccess), Function.createDelegate(this, this.OnLoadFailed)
                );
        }

    }

    function OnLoadSuccess(myList) {
        var fieldInfo = '';
        var fieldschema = termField.get_schemaXml();
        taxconfig.Configuration = fieldschema;
        taxconfig.ParseConfiguration();
        try {
            var taxsspId = taxconfig.SspId;
            var termSetId = taxconfig.TermSetId;
            var dictionaryTerms = '';
            GetTermsRecursive(taxconfig.SspId, taxconfig.TermSetId, dictionaryTerms);
             getVals('A');
        }   catch (e) {
            alert(e);
        }
    }
       function onCreateSucceeded() {
        // just an empty function
    }
//-------------------------------------------------------------------------------------

function searchKeyPress(e)
    {
        // look for window.event in case event isn't passed in
        if (typeof e == 'undefined' && window.event) { e = window.event; }
        if (e.keyCode == 13)
        {

            var mySearchField = document.getElementById('txtSearch');
             myGlobalSearch  = mySearchField.value;
            document.getElementById('btnSearch').click();
            getVals(mySearchField.value);
        }
    }

  
function getTerm() {
   var mySearchField = document.getElementById('txtSearch');
   myGlobalSearch = mySearchField.value;
   getVals(mySearchField.value);

}


function  clearMe() {
   var myfield2 = document.getElementById('txtSearch');
   myfield2.autocomplete = "off";
   myfield2.value = "";
}

 

Dictionary.js

function onFilterQueryFailed(sender, args) { alert ("Unable to retrieve terms. Please contact your administrator.") }

function getVals(letter) {
       var fieldDisplayName = "Title";
        var clientContext = new SP.ClientContext.get_current();     
       var spWebobj = clientContext.get_web();
        var spListobj = spWebobj.get_lists().getByTitle('Dictionary');
        var spCamlQuery = new SP.CamlQuery();
        spCamlQuery.set_viewXml ('<View><Query><Where><BeginsWith><FieldRef Name=\'Title\'/>' +   '<Value Type=\'Text\'>' + letter + '</Value></BeginsWith></Where><OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy></Query></View> ' );      
       this.collListItem = spListobj.getItems(spCamlQuery);
        clientContext.load(collListItem);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onFilterQueryFailed));               

      }   


function getAllVals() {
var fieldDisplayName = "Title";
        var clientContext = new SP.ClientContext.get_current();     
        var spWebobj = clientContext.get_web();
        var spListobj = spWebobj.get_lists().getByTitle('Dictionary');
        var spCamlQuery = new SP.CamlQuery();
        spCamlQuery.set_viewXml ('<View><Query><Where><IsNotNull><FieldRef Name="Title" /></IsNotNull></Where><OrderBy><FieldRef Name="Title" Ascending="True" /></OrderBy></Query></View> ');

        this.collListItem = spListobj.getItems(spCamlQuery);
        clientContext.load(collListItem);
        clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onFilterQueryFailed));

}

function onQuerySucceeded(sender, args) {
    var listItemInfo = '';
    var listItemEnumerator = collListItem.getEnumerator();
    document.getElementById("ShowMeTerm").innerHTML ='';
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        listItemInfo += '\nID: ' + oListItem.get_id() +
            '\nTitle: ' + oListItem.get_item('Title') +
            '\nBody: ' + oListItem.get_item('Definition');
          myterm =   oListItem.get_item('Title');
     document.getElementById("ShowMeTerm").innerHTML += oListItem.get_item('Title') + ":<br />" +  "<div style=color:black; font-weight:normal;>" + oListItem.get_item('Definition') +  "</div> <br /><br />" ;
       }


     if (listItemInfo.toString()== "") {
        document.getElementById("ShowMeTerm").innerHTML = "No matches found."
     }
}

Customizing SharePoint 2010 Blog Posts

In this article I will explain how it’s possible to make style customizations to SharePoint blogs. When a blog site is created, SharePoint builds a list called Post. This list contains all the articles published to the blog. The goal to this customization is to add another column to the list called ‘Written by’ and use a column type of Person or Group. The reason for this column is to display the author’s name of the post instead of showing the ‘Created By’ column. Created by displays the name of the person who published the post. Written by column by will display a choosen name instead.

blog

Blogs are customized in SharePoint using XSLT. Remember that XSLT is a style transformer for XML data. Merging XSLT with XML data will output a results page, in our case, the blog postings.

To Begin Customization
A default.aspx page is also created as the home page for the blog. Before you make any changes in Designer, its a good idea to make a backup copy of the .aspx files you plan on editing. You know its very easy to break SharePoint so be careful and protect yourself with backups!

Open default.aspx in Designer and in the Design view click on the XSltListViewWebPart so it is highlighted. When the ribbon changes to ListViewTools, select the Design tab.

design

Click on the Customize XSLT dropdown and the select ‘Customize the entire view’. This action pulls the XSL from the blog.xsl into the page so it can be viewed and customized.
Blog.xsl is an XSLT file that resides in the _layouts folder on the front end web server.
The object here is to view the .xsl file that is being used and to customize that file.

Look for the line of code:

<xsl:include href="/_layouts/xsl/blog.xsl"/> 

Move your curosr over the code and press control key to see cursor change. Control-Click on the code and a blog.xsl will open as a new page in Designer. Save a copy of blog.xsl and put it in a directory such as ‘XSL’ in the root site of the Site Collection. Give it a different name.

Close default.aspx without saving changes. Open it again and the look for the tag. Add the Written by tag as shown below:

<ViewFields>
<FieldRef Name="Title"/>
<FieldRef Name="Body"/>
<FieldRef Name="Author"/>
<FieldRef Name="PostedByWithDate"/>
<FieldRef Name="CategoryWithLink"/>
<FieldRef Name="Permalink"/>
<FieldRef Name="EmailPostLink"/>
<FieldRef Name="NumCommentsWithLink"/>
<FieldRef Name="PublishedDate"/>
<FieldRef Name="PostCategory"/>
<FieldRef Name="Written_x0020_By"/>
</ViewFields>

Save the file. Go to your saved blog.xsl file and go to the following section:


<xsl:when test="@Name='Author'"><span class="ms-postfootercolor"><xsl:value-of select="'by '"/></span><xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&amp;nbsp;</xsl:text><xsl:value-of select="$thisNode/@Author.span" disable-output-escaping="yes" /></xsl:when>

and replace the code with this:


<!-- For the author field, render it using the span style and preceed it with the word "by"--> 
<xsl:when test="@Name='Author'">
<xsl:variable name="ShowPerson">
<xsl:choose>
<xsl:when test="string-length($thisNode/@Written_x0020_By.id) &gt; 0">
<xsl:value-of select="$thisNode/@Written_x0020_By.span" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$thisNode/@Author.span" disable-output-escaping="yes" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<span class="ms-postfootercolor" ><xsl:value-of select="'by '"/></span>
<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime">&amp;nbsp;</xsl:text>

<span class="ms-postfootercolor" style="background-color:yellow; font-weight:bold"> <xsl:value-of select="$ShowPerson" disable-output-escaping="yes" /></span>
</xsl:when>

The last step you need to do is link the new xslt stylesheet to the webpart. In the browser, open the Tool Pane for the ListView web part and expand Miscellaneous.
In the XSL field, add the path name to your newly created XSLT file that you saved in XSL document library. Save your changes.

mis

Now when you view the Post page in the browser you should see the name of the person you choose in the Written by column in yellow. Feel free to change yellow to transparent or you can remove the style altogether.

yellow

Thanks to Marc Anderson for his XSLT code.

Linking CSS Style sheets via Javascript

If you are branding a SharePoint 2010 site and need to add style sheets to the page, you can do it programmatically through Javascript.
In one example, I needed to stylize the OSSSearchResults.aspx page because the refinements were not rendering too far to the right of the page.
OSSSearchResults.aspx is not a web part page, so it cannot be edited in SharePoint Designer.
The file also resides on SharePoint web front end server in the 14 hive so it’s also not a good idea to modify the css inside the actual file.
If an Administrator installed a new service pack, it’s likely to overwrite any changes you made to it.
I wanted to apply some css changes just to this page and not affect any other SharePoint page so one solution I developed was by
injecting a script link to a css file using Javascript. I applied this code to the bottom of my masterpage.


<script type="text/javascript">

function getHost() {
  var url= window.location.href;
  var nohttp = url.split('_layouts')[1];
  var hostPort = nohttp.split('_layouts')[1]

if ( hostPort.substring (1,10) == 'OSSSearch' ) {
  var $ = document; // shortcut
  var cssId = 'myCss';

if (!$.getElementById(cssId))
{
       var headtg = document.getElementsByTagName('head')[0];

   if (!headtg) {
       return;
    }

    var linktg = document.createElement('link');
    linktg.type = 'text/css';
    linktg.rel = 'stylesheet';
    linktg.href = '/Style Library/teamThemeImages/osssearchResults.css';
    linktg.title = 'Fix Layout';
    headtg.appendChild(linktg);
    }

  }

}

</script>

In my example, osssearchResults.css had just a small snippet of code. During CSS testing, I like to use ‘Background-color:red !important;’ just to make sure I am applying the style to the correct element.


.s4-ca.s4-ca-dlgNoRibbon{
             margin-left: -70px !important;
             margin-top: -60px !important;
             background-color:  transparent;

}

On the masterpage, I added the function to the body tag.

<body scroll="no"   onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();getHost()">

Make sure your masterpage and .css files are checked in and approved before testing the results in the browser.
To test the page, do a search and see how the OSSSearchResults.aspx will render with your new css!
This technique can be applied in various different methods depending on the type of customization you are applying to your SharePoint site.

Happy coding.