571 lines
19 KiB
JavaScript
571 lines
19 KiB
JavaScript
// The IDs of all code snippet sets on the same page are stored so that we can keep them in synch when a tab is
|
|
// selected.
|
|
var allTabSetIds = new Array();
|
|
|
|
// The IDs of language-specific text (LST) spans are used as dictionary keys so that we can get access to the
|
|
// spans and update them when the user changes to a different language tab. The values of the dictionary
|
|
// objects are pipe separated language-specific attributes (lang1=value|lang2=value|lang3=value). The language
|
|
// ID can be specific (cs, vb, cpp, etc.) or may be a neutral entry (nu) which specifies text common to multiple
|
|
// languages. If a language is not present and there is no neutral entry, the span is hidden for all languages
|
|
// to which it does not apply.
|
|
var allLSTSetIds = new Object();
|
|
|
|
// Help 1 persistence support. This code must appear inline.
|
|
var isHelp1;
|
|
|
|
var curLoc = document.location + ".";
|
|
|
|
if(curLoc.indexOf("mk:@MSITStore") == 0)
|
|
{
|
|
isHelp1 = true;
|
|
curLoc = "ms-its:" + curLoc.substring(14, curLoc.length - 1);
|
|
document.location.replace(curLoc);
|
|
}
|
|
else
|
|
if(curLoc.indexOf("ms-its:") == 0)
|
|
isHelp1 = true;
|
|
else
|
|
isHelp1 = false;
|
|
|
|
// The OnLoad method
|
|
function OnLoad(defaultLanguage)
|
|
{
|
|
var defLang;
|
|
|
|
if(typeof(defaultLanguage) == "undefined" || defaultLanguage == null || defaultLanguage == "")
|
|
defLang = "vb";
|
|
else
|
|
defLang = defaultLanguage;
|
|
|
|
// This is a hack to fix the URLs for the background images on certain styles. Help Viewer 1.0 doesn't
|
|
// mind if you put the relative URL in the styles for fix up later in script. However, Help Viewer 2.0 will
|
|
// abort all processing and won't run any startup script if it sees an invalid URL in the style. As such, we
|
|
// put a dummy attribute in the style to specify the image filename and use this code to get the URL from the
|
|
// Favorites icon and then substitute the background image icons in the URL and set it in each affected style.
|
|
// This works in either version of the help viewer.
|
|
var iconPath = undefined;
|
|
|
|
try
|
|
{
|
|
var linkEnum = document.getElementsByTagName("link");
|
|
|
|
for(var idx = 0; idx < linkEnum.length; idx++)
|
|
{
|
|
var link = linkEnum[idx];
|
|
|
|
if(link.rel.toLowerCase() == "shortcut icon")
|
|
iconPath = link.href.toString();
|
|
}
|
|
}
|
|
catch(e) { }
|
|
finally { }
|
|
|
|
if(iconPath)
|
|
{
|
|
try
|
|
{
|
|
var styleSheetEnum = document.styleSheets;
|
|
|
|
for(var idx = 0; idx < styleSheetEnum.length; idx++)
|
|
{
|
|
var styleSheet = styleSheetEnum[idx];
|
|
|
|
// Ignore sheets at ms-help URLs
|
|
if(styleSheet.href != null && styleSheet.href.substr(0, 8) == "ms-help:")
|
|
continue;
|
|
|
|
// Ignore errors (Help Viewer 2). styleSheet.rules is inaccessible due to security restrictions
|
|
// for all style sheets not defined within the page.
|
|
try
|
|
{
|
|
// Get sheet rules
|
|
var rules = styleSheet.rules;
|
|
|
|
if(rules == null)
|
|
rules = styleSheet.cssRules;
|
|
|
|
if(rules != null)
|
|
if(rules.length != 0)
|
|
for(var ruleNdx = 0; ruleNdx != rules.length; ruleNdx++)
|
|
{
|
|
var rule = rules.item(ruleNdx);
|
|
|
|
var selectorText = rule.selectorText.toLowerCase();
|
|
|
|
// The selector text may show up grouped or individually for these
|
|
if(selectorText == ".oh_codesnippetcontainertableftactive, .oh_codesnippetcontainertableft, .oh_codesnippetcontainertableftdisabled" ||
|
|
selectorText == ".oh_codesnippetcontainertableftactive" ||
|
|
selectorText == ".oh_codesnippetcontainertableft" ||
|
|
selectorText == ".oh_codesnippetcontainertableftdisabled")
|
|
{
|
|
rule.style.backgroundImage = "url(" + iconPath.replace("favicon.ico", "tabLeftBG.gif") + ")";
|
|
}
|
|
|
|
if(selectorText == ".oh_codesnippetcontainertabrightactive, .oh_codesnippetcontainertabright, .oh_codesnippetcontainertabrightdisabled" ||
|
|
selectorText == ".oh_codesnippetcontainertabrightactive" ||
|
|
selectorText == ".oh_codesnippetcontainertabright" ||
|
|
selectorText == ".oh_codesnippetcontainertabrightdisabled")
|
|
{
|
|
rule.style.backgroundImage = "url(" + iconPath.replace("favicon.ico", "tabRightBG.gif") + ")";
|
|
}
|
|
|
|
if(selectorText == ".oh_footer")
|
|
{
|
|
rule.style.backgroundImage = "url(" + iconPath.replace("favicon.ico", "footer_slice.gif") + ")";
|
|
}
|
|
}
|
|
}
|
|
catch(e) { }
|
|
finally { }
|
|
}
|
|
}
|
|
catch(e) { }
|
|
finally { }
|
|
}
|
|
|
|
// In MS Help Viewer, the transform the topic is ran through can move the footer. Move it back where it
|
|
// belongs if necessary.
|
|
try
|
|
{
|
|
var footer = document.getElementById("OH_footer")
|
|
|
|
if(footer)
|
|
{
|
|
var footerParent = document.body;
|
|
|
|
if(footer.parentElement != footerParent)
|
|
{
|
|
footer.parentElement.removeChild(footer);
|
|
footerParent.appendChild(footer);
|
|
}
|
|
}
|
|
}
|
|
catch(e) { }
|
|
finally { }
|
|
|
|
var language = GetLanguageCookie("CodeSnippetContainerLanguage", defLang);
|
|
|
|
// If LST exists on the page, set the LST to show the user selected programming language
|
|
UpdateLST(language);
|
|
|
|
// If code snippet groups exist, set the current language for them
|
|
if(allTabSetIds.length > 0)
|
|
{
|
|
var i = 0;
|
|
|
|
while(i < allTabSetIds.length)
|
|
{
|
|
var tabCount = 1;
|
|
|
|
// The tab count may vary so find the last one in this set
|
|
while(document.getElementById(allTabSetIds[i] + "_tab" + tabCount) != null)
|
|
tabCount++;
|
|
|
|
tabCount--;
|
|
|
|
// If not grouped, skip it
|
|
if(tabCount < 2)
|
|
{
|
|
// Disable the Copy Code link if in Chrome
|
|
if(navigator.userAgent.toLowerCase().indexOf("chrome") != -1)
|
|
document.getElementById(allTabSetIds[i] + "_copyCode").style.display = "none";
|
|
}
|
|
else
|
|
SetCurrentLanguage(allTabSetIds[i], language, tabCount);
|
|
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This function executes in the OnLoad event and ChangeTab action on code snippets. The function parameter
|
|
// is the user chosen programming language. This function iterates through the "allLSTSetIds" dictionary object
|
|
// to update the node value of the LST span tag per the user's chosen programming language.
|
|
function UpdateLST(language)
|
|
{
|
|
for(var lstMember in allLSTSetIds)
|
|
{
|
|
var devLangSpan = document.getElementById(lstMember);
|
|
|
|
if(devLangSpan != null)
|
|
{
|
|
// There may be a carriage return before the LST span in the content so the replace function below
|
|
// is used to trim the whitespace at the end of the previous node of the current LST node.
|
|
if(devLangSpan.previousSibling != null && devLangSpan.previousSibling.nodeValue != null)
|
|
devLangSpan.previousSibling.nodeValue = devLangSpan.previousSibling.nodeValue.replace(/\s+$/, "");
|
|
|
|
var langs = allLSTSetIds[lstMember].split("|");
|
|
var k = 0;
|
|
var keyValue;
|
|
|
|
while(k < langs.length)
|
|
{
|
|
keyValue = langs[k].split("=");
|
|
|
|
if(keyValue[0] == language)
|
|
{
|
|
devLangSpan.innerHTML = keyValue[1];
|
|
break;
|
|
}
|
|
|
|
k++;
|
|
}
|
|
|
|
// If not found, default to the neutral language. If there is no neutral language entry, clear the
|
|
// content to hide it.
|
|
if(k >= langs.length)
|
|
{
|
|
if(language != "nu")
|
|
{
|
|
k = 0;
|
|
|
|
while(k < langs.length)
|
|
{
|
|
keyValue = langs[k].split("=");
|
|
|
|
if(keyValue[0] == "nu")
|
|
{
|
|
devLangSpan.innerHTML = keyValue[1];
|
|
break;
|
|
}
|
|
|
|
k++;
|
|
}
|
|
}
|
|
|
|
if(k >= langs.length)
|
|
devLangSpan.innerHTML = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the selected language cookie
|
|
function GetLanguageCookie(cookieName, defaultValue)
|
|
{
|
|
if(isHelp1)
|
|
{
|
|
try
|
|
{
|
|
var globals = Help1Globals;
|
|
|
|
var value = globals.Load(cookieName);
|
|
|
|
if(value == null)
|
|
value = defaultValue;
|
|
|
|
return value;
|
|
}
|
|
catch(e)
|
|
{
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
var cookie = document.cookie.split("; ");
|
|
|
|
for(var i = 0; i < cookie.length; i++)
|
|
{
|
|
var crumb = cookie[i].split("=");
|
|
|
|
if(cookieName == crumb[0])
|
|
return unescape(crumb[1])
|
|
}
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
// Set the selected language cookie
|
|
function SetLanguageCookie(name, value)
|
|
{
|
|
if(isHelp1)
|
|
{
|
|
try
|
|
{
|
|
var globals = Help1Globals;
|
|
|
|
globals.Save(name, value);
|
|
}
|
|
catch(e)
|
|
{
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
var today = new Date();
|
|
|
|
today.setTime(today.getTime());
|
|
|
|
// Set the expiration time to be 60 days from now (in milliseconds)
|
|
var expires_date = new Date(today.getTime() + (60 * 1000 * 60 * 60 * 24));
|
|
|
|
document.cookie = name + "=" + escape(value) + ";expires=" + expires_date.toGMTString() + ";path=/";
|
|
}
|
|
|
|
// Add a language-specific text ID
|
|
function AddLanguageSpecificTextSet(lstId)
|
|
{
|
|
var keyValue = lstId.split("?")
|
|
|
|
allLSTSetIds[keyValue[0]] = keyValue[1];
|
|
}
|
|
|
|
// Add a language tab set ID
|
|
function AddLanguageTabSet(tabSetId)
|
|
{
|
|
allTabSetIds.push(tabSetId);
|
|
}
|
|
|
|
// Switch the active tab for all of other code snippets
|
|
function ChangeTab(tabSetId, language, snippetIdx, snippetCount)
|
|
{
|
|
SetLanguageCookie("CodeSnippetContainerLanguage", language);
|
|
|
|
SetActiveTab(tabSetId, snippetIdx, snippetCount);
|
|
|
|
// If LST exists on the page, set the LST to show the user selected programming language
|
|
UpdateLST(language);
|
|
|
|
var i = 0;
|
|
|
|
while(i < allTabSetIds.length)
|
|
{
|
|
// We just care about other snippets
|
|
if(allTabSetIds[i] != tabSetId)
|
|
{
|
|
// Other tab sets may not have the same number of tabs
|
|
var tabCount = 1;
|
|
|
|
while(document.getElementById(allTabSetIds[i] + "_tab" + tabCount) != null)
|
|
tabCount++;
|
|
|
|
tabCount--;
|
|
|
|
// If not grouped, skip it
|
|
if(tabCount > 1)
|
|
SetCurrentLanguage(allTabSetIds[i], language, tabCount);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// Sets the current language in the specified tab set
|
|
function SetCurrentLanguage(tabSetId, language, tabCount)
|
|
{
|
|
var tabIndex = 1;
|
|
|
|
while(tabIndex <= tabCount)
|
|
{
|
|
var tabTemp = document.getElementById(tabSetId + "_tab" + tabIndex);
|
|
|
|
if(tabTemp != null && tabTemp.innerHTML.indexOf("'" + language + "'") != -1)
|
|
break;
|
|
|
|
tabIndex++;
|
|
}
|
|
|
|
if(tabIndex > tabCount)
|
|
{
|
|
// Select the first non-disabled tab
|
|
tabIndex = 1;
|
|
|
|
if(document.getElementById(tabSetId + "_tab1").className.indexOf("OH_CodeSnippetContainerTabDisabled") != -1)
|
|
{
|
|
tabIndex++;
|
|
|
|
while(tabIndex <= tabCount)
|
|
{
|
|
var tab = document.getElementById(tabSetId + "_tab" + tabIndex);
|
|
|
|
if(tab.className.indexOf("OH_CodeSnippetContainerTabDisabled") == -1)
|
|
{
|
|
tab.className = "OH_CodeSnippetContainerTabActiveNotFirst";
|
|
document.getElementById(tabSetId + "_code_Div" + j).style.display = "block";
|
|
break;
|
|
}
|
|
|
|
tabIndex++;
|
|
}
|
|
|
|
// Disable left most image if first tab is disabled
|
|
document.getElementById(tabSetId + "_tabimgleft").className = "OH_CodeSnippetContainerTabLeftDisabled";
|
|
}
|
|
}
|
|
|
|
SetActiveTab(tabSetId, tabIndex, tabCount);
|
|
|
|
// Disable right most image if last tab is disabled
|
|
if(document.getElementById(tabSetId + "_tab" + tabCount).className.indexOf("OH_CodeSnippetContainerTabDisabled") != -1)
|
|
document.getElementById(tabSetId + "_tabimgright").className = "OH_CodeSnippetContainerTabRightDisabled";
|
|
}
|
|
|
|
// Set the active tab within a tab set
|
|
function SetActiveTab(tabSetId, tabIndex, tabCount)
|
|
{
|
|
var i = 1;
|
|
|
|
while(i <= tabCount)
|
|
{
|
|
var tabTemp = document.getElementById(tabSetId + "_tab" + i);
|
|
|
|
if(tabTemp.className == "OH_CodeSnippetContainerTabActive")
|
|
tabTemp.className = "OH_CodeSnippetContainerTabFirst";
|
|
else
|
|
if(tabTemp.className == "OH_CodeSnippetContainerTabActiveNotFirst")
|
|
tabTemp.className = "OH_CodeSnippetContainerTab";
|
|
else
|
|
if(tabTemp.className.indexOf("OH_CodeSnippetContainerTabDisabled") != -1)
|
|
{
|
|
tabTemp.firstChild.style.color = "#a8a8a8";
|
|
tabTemp.firstChild.style.fontWeight = "normal";
|
|
}
|
|
|
|
var codeTemp = document.getElementById(tabSetId + "_code_Div" + i);
|
|
|
|
if(codeTemp.style.display != "none")
|
|
codeTemp.style.display = "none";
|
|
|
|
i++;
|
|
}
|
|
|
|
if(document.getElementById(tabSetId + "_tab" + tabIndex).className.indexOf("OH_CodeSnippetContainerTabDisabled") == -1)
|
|
{
|
|
if(tabIndex == 1)
|
|
document.getElementById(tabSetId + "_tab" + tabIndex).className = "OH_CodeSnippetContainerTabActive";
|
|
else
|
|
document.getElementById(tabSetId + "_tab" + tabIndex).className = "OH_CodeSnippetContainerTabActiveNotFirst";
|
|
}
|
|
else
|
|
{
|
|
document.getElementById(tabSetId + "_tab" + tabIndex).firstChild.style.color = "black";
|
|
document.getElementById(tabSetId + "_tab" + tabIndex).firstChild.style.fontWeight = "bold";
|
|
}
|
|
|
|
document.getElementById(tabSetId + "_code_Div" + tabIndex).style.display = "block";
|
|
|
|
// Change the CSS of the first/last image div according the currently selected tab
|
|
if(tabIndex == 1 && document.getElementById(tabSetId + "_tab" + tabIndex).className.indexOf("OH_CodeSnippetContainerTabDisabled") == -1)
|
|
document.getElementById(tabSetId + "_tabimgleft").className = "OH_CodeSnippetContainerTabLeftActive";
|
|
else
|
|
if(document.getElementById(tabSetId + "_tabimgleft").className != "OH_CodeSnippetContainerTabLeftDisabled")
|
|
document.getElementById(tabSetId + "_tabimgleft").className = "OH_CodeSnippetContainerTabLeft";
|
|
|
|
if(tabIndex == tabCount && document.getElementById(tabSetId + "_tab" + tabIndex).className.indexOf("OH_CodeSnippetContainerTabDisabled") == -1)
|
|
document.getElementById(tabSetId + "_tabimgright").className = "OH_CodeSnippetContainerTabRightActive";
|
|
else
|
|
if(document.getElementById(tabSetId + "_tabimgright").className != "OH_CodeSnippetContainerTabRightDisabled")
|
|
document.getElementById(tabSetId + "_tabimgright").className = "OH_CodeSnippetContainerTabRight";
|
|
|
|
// Show copy code button if not in Chrome
|
|
if(navigator.userAgent.toLowerCase().indexOf("chrome") == -1)
|
|
document.getElementById(tabSetId + "_copyCode").style.display = "inline";
|
|
else
|
|
document.getElementById(tabSetId + "_copyCode").style.display = "none";
|
|
}
|
|
|
|
// Copy the code from the active tab of the given tab set to the clipboard
|
|
function CopyToClipboard(tabSetId)
|
|
{
|
|
var tabTemp, contentId;
|
|
var i = 1;
|
|
|
|
do
|
|
{
|
|
contentId = tabSetId + "_code_Div" + i;
|
|
tabTemp = document.getElementById(contentId);
|
|
|
|
if(tabTemp != null && tabTemp.style.display != "none")
|
|
break;
|
|
|
|
i++;
|
|
|
|
} while(tabTemp != null);
|
|
|
|
if(tabTemp == null)
|
|
return;
|
|
|
|
if(window.clipboardData)
|
|
{
|
|
try
|
|
{
|
|
window.clipboardData.setData("Text", document.getElementById(contentId).innerText);
|
|
}
|
|
catch(e)
|
|
{
|
|
alert("Permission denied. Enable copying to the clipboard.");
|
|
}
|
|
}
|
|
else if(window.netscape)
|
|
{
|
|
try
|
|
{
|
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
|
|
|
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(
|
|
Components.interfaces.nsIClipboard);
|
|
|
|
if(!clip)
|
|
return;
|
|
|
|
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(
|
|
Components.interfaces.nsITransferable);
|
|
|
|
if(!trans)
|
|
return;
|
|
|
|
trans.addDataFlavor("text/unicode");
|
|
|
|
var str = new Object();
|
|
var len = new Object();
|
|
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(
|
|
Components.interfaces.nsISupportsString);
|
|
|
|
var copytext = document.getElementById(contentId).textContent;
|
|
|
|
str.data = copytext;
|
|
trans.setTransferData("text/unicode", str, copytext.length * 2);
|
|
|
|
var clipid = Components.interfaces.nsIClipboard;
|
|
|
|
clip.setData(trans, null, clipid.kGlobalClipboard);
|
|
}
|
|
catch(e)
|
|
{
|
|
alert("Permission denied. Enter \"about:config\" in the address bar and double-click the \"signed.applets.codebase_principal_support\" setting to enable copying to the clipboard.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Help 1 persistence object. This requires a hidden input element on the page with a class of "userDataStyle"
|
|
// defined in the style sheet that implements the user data binary behavior:
|
|
// <input type="hidden" id="userDataCache" class="userDataStyle" />
|
|
var Help1Globals =
|
|
{
|
|
UserDataCache: function()
|
|
{
|
|
var userData = document.getElementById("userDataCache");
|
|
|
|
return userData;
|
|
},
|
|
|
|
Load: function(key)
|
|
{
|
|
var userData = this.UserDataCache();
|
|
|
|
userData.load("userDataSettings");
|
|
|
|
var value = userData.getAttribute(key);
|
|
|
|
return value;
|
|
},
|
|
|
|
Save: function(key, value)
|
|
{
|
|
var userData = this.UserDataCache();
|
|
userData.setAttribute(key, value);
|
|
userData.save("userDataSettings");
|
|
}
|
|
};
|