update vor token
141
API_NetFramework/VSdoc/msdn2019/chm_msdn2019.css
Normal file
@@ -0,0 +1,141 @@
|
||||
/* CHM (IE11) overrides for msdn2019.css */
|
||||
|
||||
/*********** Apply the values of the CSS variables from msdn2019.css explicitly. The CSS variables are not supported in IE 11 used by CHM viewer. */
|
||||
/*#region Common */
|
||||
|
||||
a {
|
||||
color: #1364c4;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #1364c4;
|
||||
}
|
||||
|
||||
/*#endregion Common */
|
||||
|
||||
|
||||
|
||||
/*#region HEADER */
|
||||
|
||||
|
||||
#header-top-container {
|
||||
background-color: #e3e3e3;
|
||||
}
|
||||
|
||||
/*#endregion HEADER end */
|
||||
|
||||
|
||||
.metadata {
|
||||
color: #5e5e5e;
|
||||
}
|
||||
|
||||
|
||||
div#footer {
|
||||
background-color: #e3e3e3;
|
||||
}
|
||||
|
||||
.alert {
|
||||
background-color: #d7eaf8;
|
||||
border: 1px solid #d7eaf8;
|
||||
}
|
||||
|
||||
/*#region Tables in main text */
|
||||
|
||||
div#mainSection table {
|
||||
border: 1px #cccccc solid;
|
||||
}
|
||||
|
||||
|
||||
div#mainSection table th {
|
||||
border: 1px #cccccc solid;
|
||||
background-color: #e3e3e3;
|
||||
}
|
||||
|
||||
div#mainSection table td {
|
||||
border: 1px #cccccc solid;
|
||||
}
|
||||
|
||||
|
||||
/* members list table, no vertical borders*/
|
||||
|
||||
div#mainSection table.memberListTable {
|
||||
border-top: 0px #e3e3e3 none;
|
||||
border-bottom: 1px #e3e3e3 solid;
|
||||
border-left: 0px #e3e3e3 none;
|
||||
border-right: 0px #e3e3e3 none;
|
||||
}
|
||||
|
||||
div#mainSection table.memberListTable th {
|
||||
border-top: 0px #e3e3e3 none;
|
||||
border-bottom: 1px #e3e3e3 solid;
|
||||
border-left: 0px #e3e3e3 none;
|
||||
border-right: 0px #e3e3e3 none;
|
||||
}
|
||||
|
||||
div #mainSection table.memberListTable td {
|
||||
border-top: 1px #e3e3e3 solid;
|
||||
border-bottom: 1px #e3e3e3 solid;
|
||||
border-left: 0px #e3e3e3 none;
|
||||
border-right: 0px #e3e3e3 none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*#endregion */
|
||||
|
||||
|
||||
/*#region Code snippets */
|
||||
|
||||
.codeSnippetTabs {
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.codeSnippetTab {
|
||||
height: 1.5rem;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
border-bottom: 0px none #e3e3e3;
|
||||
border-left: 1px solid #e3e3e3;
|
||||
}
|
||||
|
||||
.csFirstTab {
|
||||
border-left: 0px solid #e3e3e3;
|
||||
}
|
||||
|
||||
.codeSnippetTabLeftCorner, .codeSnippetTabLeftCornerActive {
|
||||
height: 1.5rem;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
border-bottom: 0px none #e3e3e3;
|
||||
border-left: 1px solid #e3e3e3;
|
||||
}
|
||||
|
||||
.codeSnippetTabRightCorner, .codeSnippetTabRightCornerActive {
|
||||
height: 1.5rem;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
border-bottom: 0px none #e3e3e3;
|
||||
border-right: 1px solid #e3e3e3;
|
||||
}
|
||||
|
||||
.codeSnippetCodeCollection {
|
||||
border-top: solid 1px #e3e3e3;
|
||||
border-right: solid 1px #e3e3e3;
|
||||
border-bottom: solid 1px #e3e3e3;
|
||||
border-left: solid 1px #e3e3e3;
|
||||
}
|
||||
|
||||
.codeSnippetToolbar {
|
||||
top: calc(1.5rem * -1);
|
||||
}
|
||||
|
||||
|
||||
/*#endregion Code snippets */
|
||||
|
||||
|
||||
|
||||
/************ Hide breadcrumbs */
|
||||
#header-breadcrumbs {
|
||||
display:none;
|
||||
}
|
||||
|
||||
#headerLinks {
|
||||
display: none;
|
||||
}
|
||||
993
API_NetFramework/VSdoc/msdn2019/chm_msdn2019.js
Normal file
@@ -0,0 +1,993 @@
|
||||
// #region PAGE INIT ***********************
|
||||
|
||||
|
||||
// Event handler attachment
|
||||
function registerEventHandler(element, event, handler) {
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(event, handler, false);
|
||||
} else if (element.attachEvent) {
|
||||
element.attachEvent('on' + event, handler);
|
||||
} else {
|
||||
element[event] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Event handler detachment
|
||||
function unregisterEventHandler(element, event, handler) {
|
||||
if (typeof element.removeEventListener === "function")
|
||||
element.removeEventListener(event, handler, false);
|
||||
else
|
||||
element.detachEvent("on" + event, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll handler.
|
||||
* @type {function()}
|
||||
*/
|
||||
function scrollHandler() {
|
||||
inPageTocElementMakeStickyOnScroll();
|
||||
}
|
||||
|
||||
|
||||
registerEventHandler(window, 'load', init);
|
||||
registerEventHandler(window, 'scroll', scrollHandler);
|
||||
|
||||
|
||||
/**
|
||||
* Internal in-page sections TOC.
|
||||
* */
|
||||
var inPageToc;
|
||||
|
||||
|
||||
function init() {
|
||||
try {
|
||||
fixMoniker();
|
||||
mergeCodeSnippets();
|
||||
loadLangFilter();
|
||||
showSelectedLanguages();
|
||||
inPageToc = new InternalToc(); // generate in-page TOC
|
||||
inPageTocElementInitSticky();
|
||||
}
|
||||
catch (e) {
|
||||
var msg = e.message;
|
||||
if (e.stack) {
|
||||
msg = msg + "/n" + e.stack;
|
||||
}
|
||||
(console.error || console.log).call(console, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #endregion PAGE INIT ***********************
|
||||
|
||||
|
||||
// #region INTERNAL TOC **********************
|
||||
|
||||
// position:sticky polyfill for IE 11
|
||||
|
||||
/**
|
||||
* Initialize position:sticky for #internal-toc-container.stickthis element.
|
||||
* */
|
||||
function inPageTocElementInitSticky() {
|
||||
inPageTocElement = document.querySelector('#internal-toc-container.stickthis');
|
||||
inPageTocElementOffset = inPageTocElement.getBoundingClientRect();
|
||||
}
|
||||
|
||||
var inPageTocElement;
|
||||
var inPageTocElementOffset;
|
||||
|
||||
/**
|
||||
* Simulate position:sticky for #internal-toc-container.stickthis element.
|
||||
* */
|
||||
function inPageTocElementMakeStickyOnScroll() {
|
||||
if (window.pageYOffset > inPageTocElementOffset.top) {
|
||||
inPageTocElement.style.position = 'fixed';
|
||||
inPageTocElement.style.top = 0;
|
||||
} else {
|
||||
inPageTocElement.style.position = 'relative';
|
||||
inPageTocElement.style.top = '';
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion INTERNAL TOC **********************
|
||||
|
||||
|
||||
// #region EXPAND / COLLAPSE SECTION *********************
|
||||
|
||||
function toggleSection(sectionLinkElm) {
|
||||
var sectionDiv = sectionLinkElm.parentNode.parentNode.parentNode;
|
||||
if (hasElementClass(sectionDiv, "collapsed")) {
|
||||
expandSection(sectionLinkElm);
|
||||
} else {
|
||||
collapseSection(sectionLinkElm);
|
||||
}
|
||||
}
|
||||
|
||||
function expandSection(sectionLinkElm) {
|
||||
var sectionDiv = sectionLinkElm.parentNode.parentNode.parentNode;
|
||||
removeClassFromElement(sectionDiv, "collapsed");
|
||||
sectionLinkElm.setAttribute("title", "Collapse");
|
||||
}
|
||||
|
||||
function collapseSection(sectionLinkElm) {
|
||||
var sectionDiv = sectionLinkElm.parentNode.parentNode.parentNode;
|
||||
addClassToElement(sectionDiv, "collapsed");
|
||||
sectionLinkElm.setAttribute("title", "Expand");
|
||||
}
|
||||
|
||||
// #endregion EXPAND / COLLAPSE SECTION ***********************
|
||||
|
||||
|
||||
|
||||
// #region CODE SNIPPETS **********************
|
||||
|
||||
/**
|
||||
* Merges adjacent code snippets in different languages into
|
||||
* single code collection with tabs.
|
||||
*/
|
||||
function mergeCodeSnippets() {
|
||||
var allNodes = getElementAndTextNodes(document.body);
|
||||
var parentCodeSnippet = null;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < allNodes.length; i++) {
|
||||
var currentNode = allNodes[i];
|
||||
|
||||
var nextNode;
|
||||
if (!parentCodeSnippet) {
|
||||
// look for the first code snippet which will be a parent
|
||||
if (hasElementClass(currentNode, "codeSnippetContainer")) {
|
||||
parentCodeSnippet = currentNode;
|
||||
// snippet found, move after it
|
||||
nextNode = getNextNonChildElementOrTextNode(parentCodeSnippet);
|
||||
while (allNodes[++i] !== nextNode && i < allNodes.length) { /*empty*/ }
|
||||
i--;
|
||||
}
|
||||
|
||||
} else {
|
||||
// look for the next ADJACENT code snippet
|
||||
if (hasElementClass(currentNode, "codeSnippetContainer")) {
|
||||
// merge it with the parent
|
||||
mergeTwoCodeSnippets(parentCodeSnippet, currentNode);
|
||||
// move after adjacent snippet
|
||||
nextNode = getNextNonChildElementOrTextNode(currentNode);
|
||||
while (allNodes[++i] !== nextNode && i < allNodes.length) { /*empty*/ }
|
||||
i--;
|
||||
} else {
|
||||
// or look for the non-whitespace text
|
||||
if (currentNode.nodeType === TEXT_NODE || currentNode.nodeType === CDATA_SECTION_NODE) {
|
||||
if (currentNode.nodeValue.trim() !== "") {
|
||||
// found non empty text after parent snippet, don't merge and find next parent
|
||||
parentCodeSnippet = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var ELEMENT_NODE = 1;
|
||||
var TEXT_NODE = 3;
|
||||
var CDATA_SECTION_NODE = 4;
|
||||
|
||||
/**
|
||||
* Returns all elements and text nodes under the root.
|
||||
* Recursion is not used due to performance reasons.
|
||||
*
|
||||
* @param {HTMLElement} root - The root node.
|
||||
* @returns {Array<Node>} All elements and text nodes under the root.
|
||||
*/
|
||||
function getElementAndTextNodes(root) {
|
||||
var result = [];
|
||||
|
||||
var node = root.childNodes[0];
|
||||
while (node !== null) {
|
||||
switch (node.nodeType) {
|
||||
case ELEMENT_NODE:
|
||||
case TEXT_NODE:
|
||||
case CDATA_SECTION_NODE:
|
||||
result.push(node);
|
||||
break;
|
||||
}
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
node = node.firstChild;
|
||||
}
|
||||
else {
|
||||
while (node.nextSibling === null && node !== root) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
node = node.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merges two separate snippets together. The child snippet
|
||||
* becomes a part of the parent snippet. Tabs and visibility
|
||||
* are adjusted accordingly.
|
||||
* @param {Node} parentSnippet The parent snippet to merge.
|
||||
* @param {Node} childSnippet The child snippet to merge.
|
||||
*/
|
||||
function mergeTwoCodeSnippets(parentSnippet, childSnippet) {
|
||||
var childCode = getDivWithClass(childSnippet, "codeSnippetCode");
|
||||
var parentCodeCollection = getDivWithClass(parentSnippet, "codeSnippetCodeCollection");
|
||||
if (childCode && parentCodeCollection) {
|
||||
// remove existing lang code in parent, if any
|
||||
var lang = getLangOfCodeSnippetCode(childCode);
|
||||
if (lang) {
|
||||
var existingCode = getCodeSnippetCodeByLang(parentSnippet, lang);
|
||||
if (existingCode) {
|
||||
existingCode.parentNode.removeChild(existingCode);
|
||||
}
|
||||
}
|
||||
// move child code to the parent
|
||||
childCode.parentNode.removeChild(childCode);
|
||||
parentCodeCollection.appendChild(childCode);
|
||||
showHideTag(childSnippet, false);
|
||||
|
||||
// correct the tabs (bold or normal for N/A lang)
|
||||
var csCode, tab, i;
|
||||
var tabsDiv = getDivWithClass(parentSnippet, "codeSnippetTabs");
|
||||
var langs = ["codeVB", "codeCsharp", "codeCpp", "codeFsharp", "codeJScript"];
|
||||
|
||||
for (i = 0; i < langs.length; i++) {
|
||||
lang = langs[i];
|
||||
csCode = getCodeSnippetCodeByLang(parentCodeCollection, lang);
|
||||
tab = getDivWithClass(tabsDiv, lang);
|
||||
if (csCode) {
|
||||
// lang exists
|
||||
removeClassFromElement(tab, "csNaTab");
|
||||
} else {
|
||||
// lang doesn't exist
|
||||
addClassToElement(tab, "csNaTab");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a language of DIV with codeSnippetCode class.
|
||||
* @param {HTMLElement} elm The element with code to inspect.
|
||||
* @return {string} The language code: "codeVB", "codeCsharp", "codeCpp", "codeFsharp", "codeJScript" or null.
|
||||
*/
|
||||
function getLangOfCodeSnippetCode(elm) {
|
||||
if (hasElementClass(elm, "codeVB")) {
|
||||
return "codeVB";
|
||||
} else if (hasElementClass(elm, "codeCsharp")) {
|
||||
return "codeCsharp";
|
||||
} else if (hasElementClass(elm, "codeCpp")) {
|
||||
return "codeCpp";
|
||||
} else if (hasElementClass(elm, "codeFsharp")) {
|
||||
return "codeFsharp";
|
||||
} else if (hasElementClass(elm, "codeJScript")) {
|
||||
return "codeJScript";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a DIV with codeSnippetCode class with specified language class.
|
||||
* @param {HTMLElement} containerSnippet The code container element.
|
||||
* @param {string} lang The required language code.
|
||||
* @returns {HTMLElement} The found code element. Null if not found.
|
||||
*/
|
||||
function getCodeSnippetCodeByLang(containerSnippet, lang) {
|
||||
var divTags = containerSnippet.getElementsByTagName("div");
|
||||
var i;
|
||||
for (i = 0; i < divTags.length; i++) {
|
||||
if (hasElementClasses(divTags[i], new Array("codeSnippetCode", lang))) {
|
||||
return divTags[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the next node which is not a child of specified element and
|
||||
* is whether an element or text node.
|
||||
* @param {Node} nod The base HTML node for which the search will be done.
|
||||
* @returns {Node} The node found or null.
|
||||
* @remark Unlike nextSibling property, this method returns also text nodes.
|
||||
* Moreover, if there is no next sibling, this method goes higher in the hierarchy
|
||||
* and finds the next node.
|
||||
*/
|
||||
function getNextNonChildElementOrTextNode(nod) {
|
||||
// try next sibling first
|
||||
var res = nod;
|
||||
while ((res = res.nextSibling) !== null) {
|
||||
switch (res.nodeType) {
|
||||
case ELEMENT_NODE:
|
||||
case TEXT_NODE:
|
||||
case CDATA_SECTION_NODE:
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// no sibling element or text found, try higher
|
||||
if (nod.parentNode) {
|
||||
return getNextNonChildElementOrTextNode(nod.parentNode);
|
||||
} else {
|
||||
// no node found
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion CODE SNIPPETS **********************
|
||||
|
||||
|
||||
// #region COMMON UTILS **********************
|
||||
|
||||
|
||||
/**
|
||||
* Gets the first DIV element which has the specified class.
|
||||
* @param {HTMLElement} parentElm The element where to start searching.
|
||||
* @param {string} className The class name to be found.
|
||||
* @returns {HTMLElement} The found DIV element or null if not found.
|
||||
*/
|
||||
function getDivWithClass(parentElm, className) {
|
||||
var divTags = parentElm.getElementsByTagName("div");
|
||||
var i;
|
||||
for (i = 0; i < divTags.length; i++) {
|
||||
if (hasElementClass(divTags[i], className)) {
|
||||
return divTags[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether an element contains specified CSS class.
|
||||
* @param {HTMLElement} elm The element to test.
|
||||
* @param {string} className The class name to be tested.
|
||||
* @returns {boolean} A value indicating whether the element contains the class.
|
||||
*/
|
||||
function hasElementClass(elm, className) {
|
||||
if (elm.className) {
|
||||
var classes = elm.className.split(" ");
|
||||
className = className.toLowerCase();
|
||||
var i;
|
||||
for (i = 0; i < classes.length; i++) {
|
||||
if (classes[i].toLowerCase() === className) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether an element contains all specified CSS classes.
|
||||
* @param {HTMLElement} elm The element to test.
|
||||
* @param {Array<string>} classNames An array of class names.
|
||||
* @returns {boolean} A value indicating whether the element contains the classes.
|
||||
*/
|
||||
function hasElementClasses(elm, classNames) {
|
||||
if (elm.className) {
|
||||
var classes = elm.className.split(" ");
|
||||
var i, j, found;
|
||||
found = 0;
|
||||
for (j = 0; j < classNames.length; j++) {
|
||||
var className = classNames[j].toLowerCase();
|
||||
for (i = 0; i < classes.length; i++) {
|
||||
var elmClass = classes[i].toLowerCase();
|
||||
if (elmClass === className) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found === classNames.length) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes specified CSS class from an element, if any.
|
||||
* @param {HTMLElement} elm The element to process.
|
||||
* @param {string} className The class name to be removed.
|
||||
*/
|
||||
function removeClassFromElement(elm, className) {
|
||||
if (elm === null) return;
|
||||
if (elm.className) {
|
||||
var classes = elm.className.split(" ");
|
||||
className = className.toLowerCase();
|
||||
var i;
|
||||
for (i = classes.length - 1; i >= 0; i--) {
|
||||
if (classes[i].toLowerCase() === className) {
|
||||
classes.splice(i, 1);
|
||||
}
|
||||
}
|
||||
elm.className = classes.join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds specified CSS class to an element.
|
||||
* @param {HTMLElement} elm The element to process.
|
||||
* @param {string} className The class name to be added.
|
||||
*/
|
||||
function addClassToElement(elm, className) {
|
||||
if (elm === null) return;
|
||||
if (elm.className) {
|
||||
var classes = elm.className.split(" ");
|
||||
var classNameLow = className.toLowerCase();
|
||||
var i;
|
||||
for (i = classes.length - 1; i >= 0; i--) {
|
||||
if (classes[i].toLowerCase() === classNameLow) {
|
||||
// class already exists
|
||||
return;
|
||||
}
|
||||
}
|
||||
classes[classes.length] = className;
|
||||
elm.className = classes.join(" ");
|
||||
} else {
|
||||
elm.className = className;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Super fast trim. Faster than pure regex solution.
|
||||
* @returns {string} The trimmed version of the original string.
|
||||
*/
|
||||
String.prototype.trim = function () {
|
||||
var str = this.replace(/^\s\s*/, ''),
|
||||
ws = /\s/,
|
||||
i = str.length;
|
||||
while (ws.test(str.charAt(--i)));
|
||||
return str.slice(0, i + 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the specified query parameter value.
|
||||
* @param {string} name Parameter name.
|
||||
* @param {string} url Optional.
|
||||
* @returns {string} The parameter value, an empty string if parameter is present without a value, null id parameter not present.
|
||||
*/
|
||||
function getQueryParameterByName(name, url) {
|
||||
//const urlParams = new URLSearchParams(window.location.search); // not supported by IE, not a problem?
|
||||
//const myParam = urlParams.get('myParam');
|
||||
|
||||
if (!url) url = window.location.href;
|
||||
name = name.replace(/[\[\]]/g, '\\$&');
|
||||
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
|
||||
results = regex.exec(url);
|
||||
if (!results) return null;
|
||||
if (!results[2]) return '';
|
||||
return decodeURIComponent(results[2].replace(/\+/g, ' '));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of a CSS Custom Property (starting with --).
|
||||
* Pass in an element and its CSS Custom Property that you want the value of.
|
||||
* Optionally, you can determine what datatype you get back.
|
||||
*
|
||||
* @param {String} propertyName The name of the custom CSS property, including the leading --.
|
||||
* @param {String} [castAs='string'] The datatype name of the value to be retrieved. Available values are:
|
||||
* 'number', 'int', 'float', 'boolean', 'bool'. Any other or omitted value returns string.
|
||||
* @param {HTMLELement} [element=document.documentElement] The element with the CSS property.
|
||||
* Can be omitted if the property is global, defined inside the ':root { --MyProperty }' rule.
|
||||
* @returns {*} The value of the specified CSS Custom Property.
|
||||
*/
|
||||
const getCssCustomProperty = function (propertyName, castAs, element) {
|
||||
castAs = castAs || 'string'; // default value if parameter not passed
|
||||
element = element || document.documentElement; // default value if parameter not passed
|
||||
|
||||
// CSS variables are not supported in IE 11 used in CHM.
|
||||
//let response = getComputedStyle(element).getPropertyValue(propertyName);
|
||||
// Instead, use the following representation:
|
||||
//.propertyName_without--prefix:after{
|
||||
// content: value;
|
||||
//}
|
||||
propertyName = propertyName.substr(2); // remove -- prefix
|
||||
let response = getStyleRuleValue('.' + propertyName + '::after', 'content');
|
||||
if (response === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Tidy up the string if there's something to work with
|
||||
if (response.length) {
|
||||
response = response.replace(/\'|"/g, '').trim();
|
||||
}
|
||||
|
||||
// Convert the response into a whatever type we wanted
|
||||
switch (castAs) {
|
||||
case 'number':
|
||||
case 'int':
|
||||
return parseInt(response, 10);
|
||||
case 'float':
|
||||
return parseFloat(response, 10);
|
||||
case 'boolean':
|
||||
case 'bool':
|
||||
return response === 'true' || response === '1';
|
||||
}
|
||||
|
||||
// Return the string response by default
|
||||
return response;
|
||||
};
|
||||
|
||||
|
||||
function getStyleRuleValue(selector, style) {
|
||||
let value = null;
|
||||
selector = selector.toLowerCase();
|
||||
for (let i = 0; i < document.styleSheets.length; i++) {
|
||||
const mysheet = document.styleSheets[i];
|
||||
const myrules = mysheet.cssRules ? mysheet.cssRules : mysheet.rules;
|
||||
for (let j = 0; j < myrules.length; j++) {
|
||||
if (myrules[j].selectorText &&
|
||||
myrules[j].selectorText.toLowerCase() === selector) {
|
||||
value = myrules[j].style[style];
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// #endregion COMMON UTILS **********************
|
||||
|
||||
|
||||
|
||||
// #region LANGUAGE FILTER **********************
|
||||
|
||||
// Specifies which language tab is shown as default for the first time.
|
||||
// Possible values: "codeVB", "codeCsharp", "codeCpp", "codeFsharp", "codeJScript"
|
||||
var DEFAULT_LANGUAGE_TO_SHOW = "codeCsharp";
|
||||
var languageToShow = DEFAULT_LANGUAGE_TO_SHOW;
|
||||
|
||||
function loadLangFilter() {
|
||||
languageToShow = loadSetting("languageToShow", DEFAULT_LANGUAGE_TO_SHOW);
|
||||
}
|
||||
|
||||
|
||||
function saveLangFilter() {
|
||||
saveSetting("languageToShow", languageToShow);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hides/shows the language sections according to language filter
|
||||
* @param {string} langCode "VB", "Csharp", "Cpp", "Fsharp", "JScript"
|
||||
*/
|
||||
function CodeSnippet_SetLanguage(langCode) {
|
||||
languageToShow = "code" + langCode;
|
||||
showSelectedLanguages();
|
||||
saveLangFilter();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all code snippets. A snippet is a DIV with class="codeSnippetContainer".
|
||||
* @returns {Array<HTMLElement>} The found code snippets.
|
||||
*/
|
||||
function getAllCodeSnippets() {
|
||||
var divTags = document.getElementsByTagName("div");
|
||||
var snippets = new Array();
|
||||
var i, j;
|
||||
j = 0;
|
||||
for (i = 0; i < divTags.length; i++) {
|
||||
if (hasElementClass(divTags[i], "codeSnippetContainer")) {
|
||||
snippets[j++] = divTags[i];
|
||||
}
|
||||
}
|
||||
return snippets;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hides/shows the language sections according to the language filter.
|
||||
*/
|
||||
function showSelectedLanguages() {
|
||||
try {
|
||||
var snippets = getAllCodeSnippets();
|
||||
var i, j, divs, codeCollection, snippet;
|
||||
|
||||
for (i = 0; i < snippets.length; i++) {
|
||||
snippet = snippets[i];
|
||||
if (snippet.style.display !== "none") {
|
||||
var langIsNA = false;
|
||||
|
||||
// set the tabs (active/inactive)
|
||||
var tabsDiv = getDivWithClass(snippet, "codeSnippetTabs");
|
||||
// reset corners
|
||||
var leftCorner, rightCorner;
|
||||
leftCorner = getDivWithClass(tabsDiv, "codeSnippetTabLeftCorner");
|
||||
if (!leftCorner) {
|
||||
leftCorner = getDivWithClass(tabsDiv, "codeSnippetTabLeftCornerActive");
|
||||
}
|
||||
rightCorner = getDivWithClass(tabsDiv, "codeSnippetTabRightCorner");
|
||||
if (!rightCorner) {
|
||||
rightCorner = getDivWithClass(tabsDiv, "codeSnippetTabRightCornerActive");
|
||||
}
|
||||
removeClassFromElement(leftCorner, "codeSnippetTabLeftCornerActive");
|
||||
addClassToElement(leftCorner, "codeSnippetTabLeftCorner");
|
||||
removeClassFromElement(rightCorner, "codeSnippetTabRightCornerActive");
|
||||
addClassToElement(rightCorner, "codeSnippetTabRightCorner");
|
||||
|
||||
// get the tabs
|
||||
divs = tabsDiv.getElementsByTagName("div");
|
||||
var tab;
|
||||
var tabDivs = new Array();
|
||||
for (j = 0; j < divs.length; j++) {
|
||||
if (hasElementClass(divs[j], "codeSnippetTab")) {
|
||||
// it's a tab
|
||||
tab = divs[j];
|
||||
tabDivs[tabDivs.length] = tab;
|
||||
}
|
||||
}
|
||||
|
||||
// activate/deactivate the tabs
|
||||
var tabLink;
|
||||
var visibleTabs = new Array();
|
||||
for (j = 0; j < tabDivs.length; j++) {
|
||||
tab = tabDivs[j];
|
||||
|
||||
if (hasElementClass(tab, languageToShow)) {
|
||||
addClassToElement(tab, "csActiveTab");
|
||||
tabLink = tab.getElementsByTagName("a")[0];
|
||||
tabLink.removeAttribute("href");
|
||||
langIsNA = hasElementClass(tab, "csNaTab");
|
||||
} else {
|
||||
removeClassFromElement(tab, "csActiveTab");
|
||||
var shortLang = getLangOfCodeSnippetCode(tab).substring(4);
|
||||
tabLink = tab.getElementsByTagName("a")[0];
|
||||
tabLink.setAttribute("href", "javascript: CodeSnippet_SetLanguage('" + shortLang + "');");
|
||||
}
|
||||
|
||||
// get visible tabs; invisible tabs are: with not supported lang AND not active
|
||||
if (!(hasElementClass(tab, "csNaTab") && !hasElementClass(tab, "csActiveTab"))) {
|
||||
// tab is visible
|
||||
visibleTabs[visibleTabs.length] = tab;
|
||||
}
|
||||
}
|
||||
|
||||
// fix some styles (first, last) of visible tabs and corners
|
||||
for (j = 0; j < visibleTabs.length; j++) {
|
||||
tab = visibleTabs[j];
|
||||
|
||||
removeClassFromElement(tab, "csFirstTab");
|
||||
removeClassFromElement(tab, "csLastTab");
|
||||
if (j === 0) {
|
||||
addClassToElement(tab, "csFirstTab");
|
||||
if (hasElementClass(tab, "csActiveTab")) {
|
||||
removeClassFromElement(leftCorner, "codeSnippetTabLeftCorner");
|
||||
addClassToElement(leftCorner, "codeSnippetTabLeftCornerActive");
|
||||
}
|
||||
}
|
||||
if (j === visibleTabs.length - 1) {
|
||||
addClassToElement(tab, "csLastTab");
|
||||
if (hasElementClass(tab, "csActiveTab")) {
|
||||
removeClassFromElement(rightCorner, "codeSnippetTabRightCorner");
|
||||
addClassToElement(rightCorner, "codeSnippetTabRightCornerActive");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show/hide code block
|
||||
codeCollection = getDivWithClass(snippet, "codeSnippetCodeCollection");
|
||||
divs = codeCollection.getElementsByTagName("div");
|
||||
for (j = 0; j < divs.length; j++) {
|
||||
if (hasElementClass(divs[j], "codeSnippetCode")) {
|
||||
// it's a code block
|
||||
if (langIsNA) {
|
||||
showHideTag(divs[j], hasElementClass(divs[j], "codeNA"));
|
||||
} else {
|
||||
showHideTag(divs[j], hasElementClass(divs[j], languageToShow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ex) {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showHideTag(tag, visible) {
|
||||
try {
|
||||
if (visible) {
|
||||
tag.style.display = "";
|
||||
} else {
|
||||
tag.style.display = "none";
|
||||
}
|
||||
} catch (e) {
|
||||
/*empty*/
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion LANGUAGE FILTER **********************
|
||||
|
||||
|
||||
|
||||
// #region COPY CODE ***************************
|
||||
|
||||
function CopyCode(item) {
|
||||
try {
|
||||
// get the visible code block div
|
||||
var codeCollection = item.parentNode.parentNode;
|
||||
var divs = codeCollection.getElementsByTagName("div");
|
||||
var i, shownCode;
|
||||
for (i = 0; i < divs.length; i++) {
|
||||
if (hasElementClass(divs[i], "codeSnippetCode")) {
|
||||
// it's a code block
|
||||
if (divs[i].style.display !== "none") {
|
||||
shownCode = divs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shownCode) {
|
||||
// get code and remove <br>
|
||||
var code;
|
||||
code = shownCode.innerHTML;
|
||||
code = code.replace(/<br>/gi, "\n");
|
||||
code = code.replace(/<\/td>/gi, "</td>\n"); // syntax highlighter removes \n chars and puts each line in separate <td>
|
||||
code = code.trim(); // remove leading spaces which are unwanted in FF
|
||||
// get plain text
|
||||
var tmpDiv = document.createElement('div');
|
||||
tmpDiv.innerHTML = code;
|
||||
|
||||
if (typeof tmpDiv.textContent !== "undefined") {
|
||||
// standards compliant
|
||||
code = tmpDiv.textContent;
|
||||
}
|
||||
else if (typeof tmpDiv.innerText !== "undefined") {
|
||||
// IE only
|
||||
code = tmpDiv.innerText;
|
||||
}
|
||||
|
||||
try {
|
||||
// works in IE only
|
||||
window.clipboardData.setData("Text", code);
|
||||
} catch (ex) {
|
||||
popCodeWindow(code);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
/*empty*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function popCodeWindow(code) {
|
||||
try {
|
||||
var codeWindow = window.open("",
|
||||
"Copy the selected code",
|
||||
"location=0,status=0,toolbar=0,menubar =0,directories=0,resizable=1,scrollbars=1,height=400, width=400");
|
||||
codeWindow.document.writeln("<html>");
|
||||
codeWindow.document.writeln("<head>");
|
||||
codeWindow.document.writeln("<title>Copy the selected code</title>");
|
||||
codeWindow.document.writeln("</head>");
|
||||
codeWindow.document.writeln("<body bgcolor=\"#FFFFFF\">");
|
||||
codeWindow.document.writeln('<pre id="code_text">');
|
||||
codeWindow.document.writeln(escapeHTML(code));
|
||||
codeWindow.document.writeln("</pre>");
|
||||
codeWindow.document.writeln("<scr" + "ipt>");
|
||||
// the selectNode function below, converted by http://www.howtocreate.co.uk/tutorials/jsexamples/syntax/prepareInline.html
|
||||
var ftn = "function selectNode (node) {\n\tvar selection, range, doc, win;\n\tif ((doc = node.ownerDocument) && \n\t\t(win = doc.defaultView) && \n\t\ttypeof win.getSelection != \'undefined\' && \n\t\ttypeof doc.createRange != \'undefined\' && \n\t\t(selection = window.getSelection()) && \n\t\ttypeof selection.removeAllRanges != \'undefined\') {\n\t\t\t\n\t\trange = doc.createRange();\n\t\trange.selectNode(node);\n selection.removeAllRanges();\n selection.addRange(range);\n\t} else if (document.body && \n\t\t\ttypeof document.body.createTextRange != \'undefined\' && \n\t\t\t(range = document.body.createTextRange())) {\n \n\t\t \trange.moveToElementText(node);\n \trange.select();\n }\n} ";
|
||||
codeWindow.document.writeln(ftn);
|
||||
codeWindow.document.writeln("selectNode(document.getElementById('code_text'));</scr" + "ipt>");
|
||||
codeWindow.document.writeln("</body>");
|
||||
codeWindow.document.writeln("</html>");
|
||||
codeWindow.document.close();
|
||||
} catch (ex) { /*empty*/ }
|
||||
}
|
||||
|
||||
|
||||
function escapeHTML(str) {
|
||||
return str.replace(/&/g, "&").
|
||||
replace(/>/g, ">").
|
||||
replace(/</g, "<").
|
||||
replace(/"/g, """);
|
||||
}
|
||||
|
||||
function selectNode(node) {
|
||||
var selection, range, doc, win;
|
||||
if ((doc = node.ownerDocument) &&
|
||||
(win = doc.defaultView) &&
|
||||
typeof win.getSelection !== 'undefined' &&
|
||||
typeof doc.createRange !== 'undefined' &&
|
||||
(selection = window.getSelection()) &&
|
||||
typeof selection.removeAllRanges !== 'undefined') {
|
||||
|
||||
range = doc.createRange();
|
||||
range.selectNode(node);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
} else if (document.body &&
|
||||
typeof document.body.createTextRange !== 'undefined' &&
|
||||
(range = document.body.createTextRange())) {
|
||||
|
||||
range.moveToElementText(node);
|
||||
range.select();
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion COPY CODE ***************************
|
||||
|
||||
|
||||
|
||||
// #region PERSISTENCE *************************
|
||||
|
||||
/**
|
||||
* Sets the cookie value. When an optional argument is omitted, a null is used.
|
||||
* @param {string} name - The name of the cookie.
|
||||
* @param {*} value - The value of the cookie.
|
||||
* @param {Date} [expires] - The expiration date of the cookie (defaults to end of current session).
|
||||
* @param {string} [path] - The path for which the cookie is valid (defaults to path of calling document).
|
||||
* @param {string} [domain] - The domain for which the cookie is valid (defaults to domain of calling document)
|
||||
* @param {boolean} [secure] - Boolean value indicating if the cookie transmission requires a secure transmission
|
||||
*/
|
||||
function setCookie(name, value, expires, path, domain, secure) {
|
||||
var curCookie = name + "=" + escape(value) +
|
||||
(expires ? "; expires=" + expires.toGMTString() : "") +
|
||||
(path ? "; path=" + path : "") +
|
||||
(domain ? "; domain=" + domain : "") +
|
||||
(secure ? "; secure" : "");
|
||||
document.cookie = curCookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cookie value.
|
||||
* @param {string} name The name of the desired cookie.
|
||||
* @returns {string} A string containing the value of specified cookie or null if cookie does not exist.
|
||||
*/
|
||||
function getCookie(name) {
|
||||
var dc = document.cookie;
|
||||
var prefix = name + "=";
|
||||
var begin = dc.indexOf("; " + prefix);
|
||||
if (begin === -1) {
|
||||
begin = dc.indexOf(prefix);
|
||||
if (begin !== 0) return null;
|
||||
} else
|
||||
begin += 2;
|
||||
var end = document.cookie.indexOf(";", begin);
|
||||
if (end === -1)
|
||||
end = dc.length;
|
||||
return unescape(dc.substring(begin + prefix.length, end));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a cookie.
|
||||
* @param {string} name - The name of the cookie.
|
||||
* @param {string} [path] - path of the cookie (must be same as path used to create cookie)
|
||||
* @param {string} [domain] - domain of the cookie (must be same as domain used to create cookie)
|
||||
*/
|
||||
function deleteCookie(name, path, domain) {
|
||||
if (getCookie(name)) {
|
||||
document.cookie = name + "=" +
|
||||
(path ? "; path=" + path : "") +
|
||||
(domain ? "; domain=" + domain : "") +
|
||||
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fixes the moniker of the current URL. It's needed for implementation of userData in a CHM.
|
||||
* @returns {boolean} True if the fix (URL replace) was done.
|
||||
*/
|
||||
function fixMoniker() {
|
||||
var curURL = document.location + ".";
|
||||
var pos = curURL.indexOf("mk:@MSITStore");
|
||||
if (pos === 0) {
|
||||
curURL = "ms-its:" + curURL.substring(14, curURL.length - 1);
|
||||
document.location.replace(curURL);
|
||||
return false;
|
||||
}
|
||||
else { return true; }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects whether HTML5 localStotage functionality is supported.
|
||||
* @returns {boolean} A value indicating whether HTML5 localStotage functionality is supported.
|
||||
*/
|
||||
function isLocalStorageSupported() {
|
||||
var str = 'vsdocmanDetectStorage';
|
||||
try {
|
||||
localStorage.setItem(str, str);
|
||||
localStorage.removeItem(str);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveSetting(name, value) {
|
||||
// create an instance of the Date object
|
||||
var now = new Date();
|
||||
// cookie expires in one year (actually, 365 days)
|
||||
// 1000 milliseconds in a second
|
||||
now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||
// convert the value to correct String
|
||||
if (value.constructor === Boolean) {
|
||||
if (!value) {
|
||||
value = "";
|
||||
}
|
||||
}
|
||||
// IE returns wrong document.cookie if the value is empty string
|
||||
if (value === "") {
|
||||
value = "string:empty";
|
||||
}
|
||||
|
||||
// try to use localStorage (instead of old-fashioned cookies or userData)
|
||||
if (isLocalStorageSupported()) {
|
||||
localStorage.setItem(name, value);
|
||||
return;
|
||||
}
|
||||
|
||||
// we cannot use cookies in CHM, so try to use behaviors if possible
|
||||
var headerDiv; // we can use any particular DIV or other element
|
||||
headerDiv = document.getElementById("header");
|
||||
if (headerDiv.addBehavior) {
|
||||
headerDiv.style.behavior = "url('#default#userData')";
|
||||
headerDiv.expires = now.toUTCString();
|
||||
headerDiv.setAttribute(name, value);
|
||||
// Save the persistence data as "helpSettings".
|
||||
headerDiv.save("helpSettings");
|
||||
} else {
|
||||
// set the new cookie
|
||||
setCookie(name, value, now/*, "/"*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function loadSetting(name, defaultValue) {
|
||||
var res;
|
||||
|
||||
// try to use localStorage (instead of old-fashioned cookies or userData)
|
||||
if (isLocalStorageSupported()) {
|
||||
res = localStorage.getItem(name);
|
||||
} else {
|
||||
// we cannot use cookies in CHM, so try to use behaviors if possible
|
||||
var headerDiv; // we can use any particular DIV or other element
|
||||
headerDiv = document.getElementById("header");
|
||||
if (headerDiv.addBehavior) {
|
||||
headerDiv.style.behavior = "url('#default#userData')";
|
||||
headerDiv.load("helpSettings");
|
||||
res = headerDiv.getAttribute(name);
|
||||
} else {
|
||||
// get the cookie
|
||||
res = getCookie(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (res === "string:empty") {
|
||||
res = "";
|
||||
}
|
||||
if (res === null) {
|
||||
res = defaultValue;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// #endregion PERSISTENCE *************************
|
||||
|
||||
|
||||
BIN
API_NetFramework/VSdoc/msdn2019/collapsed.png
Normal file
|
After Width: | Height: | Size: 204 B |
BIN
API_NetFramework/VSdoc/msdn2019/expanded.png
Normal file
|
After Width: | Height: | Size: 197 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendclass.png
Normal file
|
After Width: | Height: | Size: 280 B |
BIN
API_NetFramework/VSdoc/msdn2019/frienddelegate.png
Normal file
|
After Width: | Height: | Size: 428 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendenum.png
Normal file
|
After Width: | Height: | Size: 265 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendevent.png
Normal file
|
After Width: | Height: | Size: 281 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendfield.png
Normal file
|
After Width: | Height: | Size: 292 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendinterface.png
Normal file
|
After Width: | Height: | Size: 293 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendmethod.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendproperty.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
API_NetFramework/VSdoc/msdn2019/friendstructure.png
Normal file
|
After Width: | Height: | Size: 231 B |
1036
API_NetFramework/VSdoc/msdn2019/msdn2019.css
Normal file
1244
API_NetFramework/VSdoc/msdn2019/msdn2019.js
Normal file
BIN
API_NetFramework/VSdoc/msdn2019/namespace.png
Normal file
|
After Width: | Height: | Size: 486 B |
BIN
API_NetFramework/VSdoc/msdn2019/privclass.png
Normal file
|
After Width: | Height: | Size: 379 B |
BIN
API_NetFramework/VSdoc/msdn2019/privdelicate.png
Normal file
|
After Width: | Height: | Size: 407 B |
BIN
API_NetFramework/VSdoc/msdn2019/privenum.png
Normal file
|
After Width: | Height: | Size: 216 B |
BIN
API_NetFramework/VSdoc/msdn2019/privevent.png
Normal file
|
After Width: | Height: | Size: 242 B |
BIN
API_NetFramework/VSdoc/msdn2019/privfield.png
Normal file
|
After Width: | Height: | Size: 245 B |
BIN
API_NetFramework/VSdoc/msdn2019/privinterface.png
Normal file
|
After Width: | Height: | Size: 250 B |
BIN
API_NetFramework/VSdoc/msdn2019/privmethod.png
Normal file
|
After Width: | Height: | Size: 304 B |
BIN
API_NetFramework/VSdoc/msdn2019/privproperty.png
Normal file
|
After Width: | Height: | Size: 364 B |
BIN
API_NetFramework/VSdoc/msdn2019/privstructure.png
Normal file
|
After Width: | Height: | Size: 160 B |
BIN
API_NetFramework/VSdoc/msdn2019/protclass.png
Normal file
|
After Width: | Height: | Size: 422 B |
BIN
API_NetFramework/VSdoc/msdn2019/protdeligate.png
Normal file
|
After Width: | Height: | Size: 403 B |
BIN
API_NetFramework/VSdoc/msdn2019/protenum.png
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
API_NetFramework/VSdoc/msdn2019/protevent.png
Normal file
|
After Width: | Height: | Size: 291 B |
BIN
API_NetFramework/VSdoc/msdn2019/protfield.png
Normal file
|
After Width: | Height: | Size: 300 B |
BIN
API_NetFramework/VSdoc/msdn2019/protinterface.png
Normal file
|
After Width: | Height: | Size: 307 B |
BIN
API_NetFramework/VSdoc/msdn2019/protmethod.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
API_NetFramework/VSdoc/msdn2019/protproperty.png
Normal file
|
After Width: | Height: | Size: 298 B |
BIN
API_NetFramework/VSdoc/msdn2019/protstructure.png
Normal file
|
After Width: | Height: | Size: 225 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubclass.png
Normal file
|
After Width: | Height: | Size: 212 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubdeligate.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubenum.png
Normal file
|
After Width: | Height: | Size: 303 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubevent.png
Normal file
|
After Width: | Height: | Size: 210 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubextensionmethod.png
Normal file
|
After Width: | Height: | Size: 542 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubfield.png
Normal file
|
After Width: | Height: | Size: 216 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubinterface.png
Normal file
|
After Width: | Height: | Size: 222 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubmethod.png
Normal file
|
After Width: | Height: | Size: 575 B |
BIN
API_NetFramework/VSdoc/msdn2019/puboperator.png
Normal file
|
After Width: | Height: | Size: 280 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubproperty.png
Normal file
|
After Width: | Height: | Size: 428 B |
BIN
API_NetFramework/VSdoc/msdn2019/pubstructure.png
Normal file
|
After Width: | Height: | Size: 167 B |
408
API_NetFramework/VSdoc/msdn2019/search.js
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* The array of document details for displayed search results. It is read from multiple small s_XY.js files.
|
||||
* Used when readCommonTitlesFile = false.
|
||||
* A single document info has format: search_result['DocumentId'] = ['Url','Title','Summary'].
|
||||
*
|
||||
* @type {Array<Array<string>>}
|
||||
* */
|
||||
var search_result = [];
|
||||
|
||||
/**
|
||||
* The array of document details for displayed search results. It is read from one large summaries s_all.sj file.
|
||||
* Used when readCommonTitlesFile = true.
|
||||
* A single document info has format: search_result['DocumentId'] = ['Url','Title','Summary'].
|
||||
*
|
||||
* @type {Array<Array<string>>}
|
||||
* */
|
||||
var _s = [];
|
||||
|
||||
/**
|
||||
* The count of results shown in one step. -1 means unlimited.
|
||||
* @type {number}
|
||||
* */
|
||||
var paginationSize = 25;
|
||||
|
||||
/**
|
||||
* Indicates whether topic titles and summaries are read from one common large file 's_all.js'
|
||||
* or whether each title will be loaded from its own file named 's_TOPIC-ID.js'.
|
||||
*
|
||||
* With a huge index, e.g. 20000 topics, the single common file may be quite large. But still it is better
|
||||
* solution, because each loading of a small file with just sibgle topic takes about 100ms, which is 2.5 seconds for 25 results.
|
||||
*
|
||||
* @type {boolean}
|
||||
* */
|
||||
var readCommonTitlesFile = true;
|
||||
|
||||
/**
|
||||
* The search terms from the user.
|
||||
* @var {Array.<string>} qterms
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes dots and spaces in a search query string.
|
||||
* @param {string} text The search query text.
|
||||
* @returns {string} Normalized search text.
|
||||
*/
|
||||
function stripSpaces(text) {
|
||||
// return text.replace(/^\W+/,'').replace(/\W+$/,'');
|
||||
text = text.replace(/\./g, ' '); // replace dots with spaces
|
||||
return text.split(" ").join(" "); // remove multiple spaces
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a search match bitmap where a bit at the specified position is set to 1.
|
||||
* A search match bitmap indicates, for which search term (qterm) a match was found
|
||||
* for a specific document.
|
||||
*
|
||||
* @param {number} setbit A zero-based index of the bit to set to 1.
|
||||
* @param {number} size A size of bitmap, which is the count of the qterms.
|
||||
* @returns {Array.<number>} The bitmap with one bit set.
|
||||
*/
|
||||
function get_bitmap(setbit, size) {
|
||||
var map = {};
|
||||
for (let i = 0; i < size; ++i) {
|
||||
map[i] = 0;
|
||||
}
|
||||
map[setbit] = 1;
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the 'qterms' global variable with the terms from the 'search' query.
|
||||
* */
|
||||
function getQtermsFromUrlQuery() {
|
||||
// extract all search terms
|
||||
var query = getQueryParameterByName("search");
|
||||
if (!query || query === "") {
|
||||
return;
|
||||
}
|
||||
var terms = stripSpaces(query.toLowerCase());
|
||||
|
||||
qterms = [];
|
||||
var chunks = terms.split(" ");
|
||||
for (let i in chunks) {
|
||||
if (chunks[i]) {
|
||||
qterms[qterms.length] = chunks[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a search according to the 'search' query parameter.
|
||||
*
|
||||
* */
|
||||
function search() {
|
||||
// extract all search terms
|
||||
getQtermsFromUrlQuery();
|
||||
|
||||
/**
|
||||
* For each document ID that has some match, contains a bitmap of matched terms and cumulative relevance.
|
||||
* @type {Object.<number, {matchBitmap:Array.<number>, relevance:number} >} */
|
||||
var candidates = {};
|
||||
|
||||
for (let qtermIndex in qterms) {
|
||||
/** @type {string} */
|
||||
let term = qterms[qtermIndex];
|
||||
let onlyWholeWord = false;
|
||||
// Read the user setting, whether he wants to always match whole words, even if no quotes around are used.
|
||||
// The user can define it in the CSS, e.g. in vsdocman_overrides.css:
|
||||
// :root {
|
||||
// --searchAlwaysWholeWord: true;
|
||||
// }
|
||||
onlyWholeWord = getCssCustomProperty("--searchAlwaysWholeWord", "boolean");
|
||||
if (term.length > 2 && term.startsWith("\"") && term.endsWith("\"")) {
|
||||
term = term.substr(1, term.length - 2);
|
||||
onlyWholeWord = true;
|
||||
}
|
||||
|
||||
// index= "term1":"[[docId1, relevance1],.., [docIdN, relevanceN]]", ..., "term5":"[[docId1, relevance1],.., [docIdN, relevanceN]]""
|
||||
|
||||
// whole words
|
||||
let termDocs=index[term]; // serialized string (instead of a direct array) for much faster parsing of search_index.js
|
||||
if (termDocs !== undefined) {
|
||||
termDocs = JSON.parse(termDocs); // deserialize
|
||||
for (let i in termDocs) {
|
||||
let docId = termDocs[i][0];
|
||||
let relevance = termDocs[i][1];
|
||||
if (candidates[docId] === undefined) {
|
||||
candidates[docId] = {};
|
||||
candidates[docId].matchBitmap = get_bitmap(qtermIndex, qterms.length);
|
||||
candidates[docId].relevance = relevance;
|
||||
}
|
||||
else {
|
||||
candidates[docId].matchBitmap[qtermIndex] = 1;
|
||||
candidates[docId].relevance += relevance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parts of words
|
||||
if (!onlyWholeWord) {
|
||||
for (let indexedTerm in index) {
|
||||
if (indexedTerm.indexOf(term) >= 0) {
|
||||
termDocs = index[indexedTerm]; // serialized string (instead of a direct array) for much faster parsing of search_index.js
|
||||
termDocs = JSON.parse(termDocs); // deserialize
|
||||
for (let i in termDocs) {
|
||||
let docId = termDocs[i][0];
|
||||
let relevance = termDocs[i][1];
|
||||
if (candidates[docId] === undefined) {
|
||||
candidates[docId] = {};
|
||||
candidates[docId].matchBitmap = get_bitmap(qtermIndex, qterms.length);
|
||||
candidates[docId].relevance = relevance;
|
||||
}
|
||||
else {
|
||||
candidates[docId].matchBitmap[qtermIndex] = 1;
|
||||
candidates[docId].relevance += relevance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let results = [];
|
||||
// sort by relevance in descending order
|
||||
let sortedDocIds = [];
|
||||
for (let key in candidates) sortedDocIds.push(key);
|
||||
sortedDocIds.sort(function (a, b) {
|
||||
return candidates[b].relevance - candidates[a].relevance;
|
||||
});
|
||||
for (let i = 0; i < sortedDocIds.length; i++) {
|
||||
let docIndex = sortedDocIds[i];
|
||||
let on = 1;
|
||||
for (let i in qterms) {
|
||||
on = on && candidates[docIndex].matchBitmap[i];
|
||||
}
|
||||
if (on) {
|
||||
results.push(docIndex);
|
||||
}
|
||||
}
|
||||
let resultsCount = results.length;
|
||||
|
||||
document.getElementById("search-results-heading-count").appendChild(document.createTextNode(resultsCount)); // safe way of setting un-escaped text
|
||||
let sPhrase = getQueryParameterByName("search");
|
||||
sPhrase = "\"" + sPhrase + "\"";
|
||||
document.getElementById("search-results-heading-phrase").appendChild(document.createTextNode(sPhrase)); // safe way of setting un-escaped text
|
||||
|
||||
var appendPromise = loadAndAppendSearchResultItems(results, 0, paginationSize);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For specified file indexes range, loads and displays the search results.
|
||||
* @param {Array.<number>} docIds The doc IDs (assigned by the indexer) of all search results.
|
||||
* @param {number} from The index of the first item to append in the docIndexes.
|
||||
* @param {number} count The count of items to append from the docIndexes.
|
||||
* @returns {Promise<number>} A promise that is resolved when the result is displayed. The value is the last file index appended.
|
||||
*/
|
||||
function loadAndAppendSearchResultItems(docIds, from, count) {
|
||||
var appendPromise = Promise.resolve(); //immediately resolving promise
|
||||
for (let i = from; i < from + count && i < docIds.length; i++) {
|
||||
appendPromise = appendPromise.then(() => loadAndAppendSearchResultItem(docIds[i]));
|
||||
}
|
||||
|
||||
appendPromise = appendPromise.then(() => {
|
||||
if (docIds.length > from + count) {
|
||||
showHidePaginationControls(true, docIds, from+count, count);
|
||||
} else {
|
||||
showHidePaginationControls(false, docIds, 0, 0);
|
||||
}
|
||||
return 0; // return anything
|
||||
});
|
||||
|
||||
return appendPromise;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows or hide pagination links.
|
||||
* @param {boolean} show Show or hide.
|
||||
* @param {Array.<number>} docIds The doc IDs (assigned by the indexer) of all search results.
|
||||
* @param {number} nextFrom The index of the next item to append in the docIndexes when the NEXT link is pressed.
|
||||
* @param {number} count The count of items to append from the docIndexes when the NEXT link is pressed..
|
||||
*/
|
||||
function showHidePaginationControls(show, docIds, nextFrom, count) {
|
||||
let paginationDiv = document.getElementById("search-results-pagination");
|
||||
if (!paginationDiv) {
|
||||
if (show) {
|
||||
// create
|
||||
let parent = document.getElementById("search-results-section");
|
||||
paginationDiv = document.createElement('div');
|
||||
paginationDiv.id = "search-results-pagination";
|
||||
parent.appendChild(paginationDiv);
|
||||
|
||||
let a = document.createElement('a');
|
||||
a.id = "search-pagination-next";
|
||||
a.href = "";
|
||||
a.appendChild(document.createTextNode("Next " + paginationSize + " >>")); // safe way of setting un-escaped text
|
||||
paginationDiv.appendChild(a);
|
||||
|
||||
a = document.createElement('a');
|
||||
a.id = "search-pagination-all";
|
||||
a.href = "";
|
||||
a.appendChild(document.createTextNode("All >>")); // safe way of setting un-escaped text
|
||||
paginationDiv.appendChild(a);
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (show) {
|
||||
paginationDiv.classList.add("visible");
|
||||
// update click actions
|
||||
let a = document.getElementById("search-pagination-next");
|
||||
a.onclick = function () {
|
||||
loadAndAppendSearchResultItems(docIds, nextFrom, count);
|
||||
return false;
|
||||
};
|
||||
|
||||
a = document.getElementById("search-pagination-all");
|
||||
a.onclick = function () {
|
||||
loadAndAppendSearchResultItems(docIds, nextFrom, docIds.length - nextFrom);
|
||||
return false;
|
||||
};
|
||||
} else {
|
||||
paginationDiv.classList.remove("visible");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For a specified file index, loads and displays the search result.
|
||||
* @param {number} fileIndex The search index (assigned by the indexer) of the result file.
|
||||
* @returns {Promise<number>} A promise that is resolved when the result is displayed. The value is fileIndex.
|
||||
*/
|
||||
function loadAndAppendSearchResultItem(fileIndex) {
|
||||
if (readCommonTitlesFile) {
|
||||
// Read the search result details from one common large file which contains all topics.
|
||||
// This method is much faster over network, but the 's_all.js' file may be quite large
|
||||
// for many, e.g. 20000, topics. So the first search will be slower, then the file will be cached.
|
||||
|
||||
// ensure the file info is loaded
|
||||
return loadScriptOnce("search--/s_all.js")
|
||||
.then(
|
||||
function (scriptWasLoadedNow) {
|
||||
// the loaded script defines all search results as _s[fileIndex]
|
||||
let url = _s[fileIndex][0];
|
||||
let title = _s[fileIndex][1];
|
||||
let summary = _s[fileIndex][2];
|
||||
appendSearchResultItem(url, title, summary);
|
||||
return fileIndex;
|
||||
});
|
||||
|
||||
} else {
|
||||
// Read the search result details from a separate small file, one for each topic.
|
||||
// This method is fast for local pages, but is slow on network, as each load of
|
||||
// a small file takes about 100ms.
|
||||
|
||||
// ensure the file info is loaded
|
||||
return loadScriptOnce("search--/s_" + fileIndex + ".js")
|
||||
.then(
|
||||
function (scriptWasLoadedNow) {
|
||||
// the loaded script defines search_result[fileIndex]
|
||||
let url = search_result[fileIndex][0];
|
||||
let title = search_result[fileIndex][1];
|
||||
let summary = search_result[fileIndex][2];
|
||||
appendSearchResultItem(url, title, summary);
|
||||
return fileIndex;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends specified search result to the list of results.
|
||||
* @param {string} url The URL of the search result.
|
||||
* @param {string} title The title of the search result.
|
||||
* @param {string} summary The summary of the search result, if any.
|
||||
*/
|
||||
function appendSearchResultItem(url, title, summary) {
|
||||
var containerElm = document.getElementById("search-results-container");
|
||||
if (!containerElm) {
|
||||
return;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.className = "search-result-item";
|
||||
|
||||
var div2 = document.createElement('div');
|
||||
div2.className = "search-result-title";
|
||||
div.appendChild(div2);
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
//a.appendChild(document.createTextNode(title)); // safe way of setting un-escaped text
|
||||
a.innerHTML = title; // 'title' is already HTML encoded
|
||||
div2.appendChild(a);
|
||||
|
||||
div2 = document.createElement('div');
|
||||
div2.className = "search-result-summary";
|
||||
div2.appendChild(document.createTextNode(summary)); // safe way of setting un-escaped text
|
||||
div.appendChild(div2);
|
||||
|
||||
containerElm.appendChild(div);
|
||||
}
|
||||
|
||||
|
||||
function highlightSearchTerms() {
|
||||
try {
|
||||
colors = ['yellow', 'lightgreen', 'gold', 'orange', 'magenta', 'lightblue'];
|
||||
getQtermsFromUrlQuery();
|
||||
if (qterms !== undefined) {
|
||||
for (let i in qterms) {
|
||||
document.body.innerHTML = doHighlight(document.body.innerHTML, qterms[i], colors[i % colors.length]);
|
||||
}
|
||||
}
|
||||
} catch (ex) { ; }
|
||||
}
|
||||
|
||||
// from http://www.nsftools.com/misc/SearchAndHighlight.htm
|
||||
|
||||
/*
|
||||
* This is the function that actually highlights a text string by
|
||||
* adding HTML tags before and after all occurrences of the search
|
||||
* term. You can pass your own tags if you'd like, or if the
|
||||
* highlightStartTag or highlightEndTag parameters are omitted or
|
||||
* are empty strings then the default <font> tags will be used.
|
||||
*/
|
||||
function doHighlight(bodyText, searchTerm, color, highlightStartTag, highlightEndTag) {
|
||||
// the highlightStartTag and highlightEndTag parameters are optional
|
||||
if (!highlightStartTag || !highlightEndTag) {
|
||||
highlightStartTag = "<font style='background-color:" + color + ";'>";
|
||||
highlightEndTag = "</font>";
|
||||
}
|
||||
|
||||
// find all occurrences of the search term in the given text,
|
||||
// and add some "highlight" tags to them (we're not using a
|
||||
// regular expression search, because we want to filter out
|
||||
// matches that occur within HTML tags and script blocks, so
|
||||
// we have to do a little extra validation)
|
||||
var newText = "";
|
||||
var i = -1;
|
||||
var lcSearchTerm = searchTerm.toLowerCase();
|
||||
var lcBodyText = bodyText.toLowerCase();
|
||||
|
||||
while (bodyText.length > 0) {
|
||||
i = lcBodyText.indexOf(lcSearchTerm, i + 1);
|
||||
if (i < 0) {
|
||||
newText += bodyText;
|
||||
bodyText = "";
|
||||
} else {
|
||||
// skip anything inside an HTML tag
|
||||
if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
|
||||
// skip anything inside a <script> block
|
||||
if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
|
||||
newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
|
||||
bodyText = bodyText.substr(i + searchTerm.length);
|
||||
lcBodyText = bodyText.toLowerCase();
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newText;
|
||||
}
|
||||
BIN
API_NetFramework/VSdoc/msdn2019/search_16.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
API_NetFramework/VSdoc/msdn2019/static.png
Normal file
|
After Width: | Height: | Size: 144 B |
181
API_NetFramework/VSdoc/msdn2019/toc.css
Normal file
@@ -0,0 +1,181 @@
|
||||
#toc-container {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.3;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#toc-container a, #toc-container a:visited {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#toc-container a:hover {
|
||||
text-decoration: underline;
|
||||
color: #1364c4;
|
||||
}
|
||||
|
||||
|
||||
#toc-container .header a {
|
||||
}
|
||||
|
||||
.toc-highlighted {
|
||||
background-color: #0065b3 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.toc-highlighted a {
|
||||
color: #fff !important;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
#toc-container .item {
|
||||
border: solid 0px #000;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
#toc-container .item.item.expanded {
|
||||
/*padding: 0.25em;*/
|
||||
}
|
||||
|
||||
#toc-container .item > div {
|
||||
border: solid 0px #000;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-height: 0px;
|
||||
font-size: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#toc-container .item.animatable > div {
|
||||
transition: all .2s ease;
|
||||
}
|
||||
|
||||
#toc-container .item.collapsed > div {
|
||||
max-height: 0px;
|
||||
font-size: 0px;
|
||||
overflow: hidden;
|
||||
transform: scale(1.0, 0.0);
|
||||
transform-origin: left top;
|
||||
/*opacity: 0;*/
|
||||
/*max-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 !important;
|
||||
border: none !important;*/
|
||||
/*font-size: 0.5rem;
|
||||
transition: all .2s ease 0s;*/
|
||||
/*transition: font-size .2s ease-out 0s;
|
||||
transition: padding .2s ease-out 0s;*/
|
||||
}
|
||||
|
||||
#toc-container .item.expanded > div {
|
||||
max-height: 100%;
|
||||
font-size: 1em;
|
||||
transform: scale(1, 1);
|
||||
transform-origin: left top;
|
||||
/*opacity: 1;*/
|
||||
/*max-height: 1000px;*/ /*real pixel size will be set by JS*/
|
||||
/*font-size: 1rem;
|
||||
transition: all .2s ease-out 0s;*/
|
||||
}
|
||||
|
||||
#toc-container .header, #toc-container .leaf {
|
||||
cursor: pointer;
|
||||
padding-left: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-top: 4px;
|
||||
min-height: 18px;
|
||||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#toc-container .closed::before {
|
||||
content: "\203A";
|
||||
speak: none;
|
||||
display: inline-block;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
direction: ltr;
|
||||
/*font-size: 150%;*/
|
||||
/*padding-right: 0.3em;*/
|
||||
margin-right: 0.3em;
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg) scale(1.5,1.5) translateY(-10%);
|
||||
}
|
||||
|
||||
#toc-container .closed.animatable::before {
|
||||
transition: transform 1.2s ease-out 0s,-webkit-transform .2s ease-out 0s;
|
||||
}
|
||||
|
||||
|
||||
#toc-container .open::before {
|
||||
content: "\203A";
|
||||
speak: none;
|
||||
display: inline-block;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
direction: ltr;
|
||||
/*font-size: 150%;*/
|
||||
/*vertical-align: middle;*/
|
||||
/*padding-right: 0.3em;*/
|
||||
-webkit-transform: rotate(90deg) scale(1.5,1.5) translateY(-15%);
|
||||
transform: rotate(90deg) scale(1.5,1.5) translateY(-15%);
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
#toc-container .open.animatable::before {
|
||||
transition: transform 1.2s ease-out 0s,-webkit-transform .2s ease-out 0s;
|
||||
}
|
||||
|
||||
|
||||
#toc-container .leaf {
|
||||
}
|
||||
|
||||
|
||||
/*#region Internal (in-page sections) TOC */
|
||||
|
||||
div#internal-toc-container {
|
||||
padding: 10px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
#internal-toc-heading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#internal-toc-heading.visible {
|
||||
display: block;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
#internal-toc-definition-localized-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#internal-toc-container ul {
|
||||
padding: 0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#internal-toc-container ul li {
|
||||
list-style: none;
|
||||
border-left: 3px solid var(--secondary-background);
|
||||
}
|
||||
|
||||
#internal-toc-container ul li.visible {
|
||||
border-left: 3px solid var(--link-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#internal-toc-container li {
|
||||
line-height: 1.3;
|
||||
font-size: .875rem;
|
||||
padding-top: 4px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 4px;
|
||||
margin: 0px 0;
|
||||
}
|
||||
|
||||
/*#endregion Internal (in-page sections) TOC */
|
||||
470
API_NetFramework/VSdoc/msdn2019/toc.js
Normal file
@@ -0,0 +1,470 @@
|
||||
|
||||
|
||||
// #region Main TOC
|
||||
|
||||
var c = [];
|
||||
|
||||
/**
|
||||
* Appends a TOC item under an existing XML element.
|
||||
* @param {HTMLElement} parentElm The parent element for the TOC item to be appended.
|
||||
* @param {Array} tocNode The TOC item to be appended. Format: ['Id','Text','Url',hasChildrenStr=0/1]
|
||||
*/
|
||||
function appendTocNode(parentElm, tocNode) {
|
||||
var id = tocNode[0];
|
||||
var text = tocNode[1];
|
||||
var url = tocNode[2];
|
||||
var hasChildren = tocNode[3];
|
||||
|
||||
if (hasChildren === 1) {
|
||||
//<div id="id" class="header closed" onclick="toggle('cID',this)">
|
||||
// <a href="url">text</a>
|
||||
//</div>
|
||||
//<div id="cID" class="item collapsed">
|
||||
// <div id="ciID" class="inner-for-height">
|
||||
// </div>
|
||||
//</div>
|
||||
var div1 = document.createElement('div');
|
||||
div1.id = id;
|
||||
div1.className = "header closed";
|
||||
div1.onclick = function () { toggle("c" + id, div1); };
|
||||
|
||||
if (url !== "") {
|
||||
var a1 = document.createElement('a');
|
||||
a1.href = url;
|
||||
a1.setAttribute('title', text);
|
||||
//a1.innerHTML = text;
|
||||
a1.appendChild(document.createTextNode(text)); // safe way of setting un-escaped text
|
||||
|
||||
div1.appendChild(a1);
|
||||
} else {
|
||||
//div1.innerHTML = text;
|
||||
div1.appendChild(document.createTextNode(text)); // safe way of setting un-escaped text
|
||||
}
|
||||
|
||||
var div2 = document.createElement('div');
|
||||
div2.id = "c" + id;
|
||||
div2.className = "item collapsed";
|
||||
|
||||
var div3 = document.createElement('div');
|
||||
div3.id = "ci" + id;
|
||||
div3.className = "inner-for-height";
|
||||
|
||||
div2.appendChild(div3);
|
||||
|
||||
parentElm.appendChild(div1);
|
||||
parentElm.appendChild(div2);
|
||||
} else {
|
||||
//<div id="id" class="leaf"><a href="url">text</a></div>
|
||||
var div = document.createElement('div');
|
||||
div.id = id;
|
||||
div.className = "leaf";
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.setAttribute('title', text);
|
||||
a.appendChild(document.createTextNode(text)); // safe way of setting un-escaped text
|
||||
//a.innerHTML = text;
|
||||
|
||||
div.appendChild(a);
|
||||
parentElm.appendChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggles expansion of a TOC chapter.
|
||||
* @param {string} idSub Id of the DIV container with subtopics.
|
||||
* @param {HTMLElement} elHead The chapter DIV element.
|
||||
*/
|
||||
function toggle(idSub, elHead) {
|
||||
elHead.classList.add("animatable"); // make header DIV animatable
|
||||
var elSub = document.getElementById(idSub);
|
||||
if (hasElementClass(elSub, "expanded")) {
|
||||
// collapse
|
||||
expandCollapseElement(elSub, false, true);
|
||||
|
||||
if (hasElementClasses(elHead, ["header", "open"])) {
|
||||
removeClassFromElement(elHead, "open");
|
||||
addClassToElement(elHead, "closed");
|
||||
}
|
||||
fitTocHeightToViewport();
|
||||
}
|
||||
else {
|
||||
// expand
|
||||
expandTocItem(elHead.id, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} element The chapter container outer DIV.
|
||||
* @param {boolean} expand Indicates whether to expand or collapse.
|
||||
* @param {boolean} animationEffects Indicates whether to show animation.
|
||||
*/
|
||||
function expandCollapseElement(element, expand, animationEffects) {
|
||||
if (expand) {
|
||||
if (animationEffects) {
|
||||
element.classList.add("animatable"); // make container DIV animatable
|
||||
}
|
||||
element.classList.replace('collapsed', 'expanded');
|
||||
} else {
|
||||
if (animationEffects) {
|
||||
element.classList.add("animatable"); // make container DIV animatable
|
||||
}
|
||||
element.classList.replace('expanded', 'collapsed');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the element height including margins.
|
||||
* @param {HTMLElement} element The element to test.
|
||||
* @returns {number} The height.
|
||||
*/
|
||||
function outerHeight(element) {
|
||||
const height = element.offsetHeight;
|
||||
const style = window.getComputedStyle(element);
|
||||
|
||||
return ['top', 'bottom']
|
||||
.map(function (side) { return parseInt(style["margin-" + side]); })
|
||||
.reduce(function (total, side) { return total + side, height; });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expands specified topic chain in the TOC and selects the terminal topic.
|
||||
* Function works asynchronously (the nodes are dynamically loaded if needed).
|
||||
* @param {Array<Array<string>>} breadcrumbs An array of topic definitions. A single TOC item
|
||||
* has format: ['Id','Text','Url'].
|
||||
* @returns {Promise<string>} A promise that is resolved after all specified nodes are expanded. The value is Id
|
||||
* of the last node.
|
||||
*/
|
||||
function expandBreadcrumbsInToc(breadcrumbs) {
|
||||
var oldScrollX = window.pageXOffset;
|
||||
var oldScrollY = window.pageYOffset;
|
||||
|
||||
var lastId;
|
||||
var expandPromise = Promise.resolve(); //immediately resolving promise
|
||||
for (i = 0; i < breadcrumbs.length; i++) {
|
||||
var tocNode = breadcrumbs[i];
|
||||
let id = tocNode[0];
|
||||
lastId = id;
|
||||
expandPromise = expandPromise.then(function () { return expandTocItem(id, false) });
|
||||
}
|
||||
|
||||
return expandPromise.then(
|
||||
function () {
|
||||
selectTocItem(lastId); //last topic in breadcrumbs
|
||||
|
||||
// The TOC expansion could scroll the page a bit. Scroll back to the original position.
|
||||
// On the next frame (as soon as the previous style change has taken effect),
|
||||
// restore the scroll position if it has changed.
|
||||
requestAnimationFrame(function () {
|
||||
window.scrollTo(oldScrollX, oldScrollY);
|
||||
});
|
||||
|
||||
return lastId;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Expands specified TOC item asynchronously (the child nodes are dynamically loaded if needed).
|
||||
* @param {string} tocItemId The ID of TOC item to expand.
|
||||
* @returns {Promise<string>} A promise that is resolved when the node is expanded. The value is tocItemId.
|
||||
* @param {boolean} animationEffects Indicates whether to show animation.
|
||||
*/
|
||||
function expandTocItem(tocItemId, animationEffects) {
|
||||
// get the chapter header
|
||||
var elmHead = document.getElementById(tocItemId);
|
||||
if (!elmHead) {
|
||||
return;
|
||||
}
|
||||
if (elmHead.className === "leaf") {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the container with subtopics
|
||||
var elmCont = document.getElementById("c" + tocItemId);
|
||||
if (hasElementClass(elmCont, "collapsed")) {
|
||||
// expand
|
||||
expandCollapseElement(elmCont, true, animationEffects);
|
||||
|
||||
// process also chapter header
|
||||
if (hasElementClasses(elmHead, ["header", "closed"])) {
|
||||
removeClassFromElement(elmHead, "closed");
|
||||
addClassToElement(elmHead, "open");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ensure the child nodes are loaded
|
||||
return loadScriptOnce("toc--/t_" + tocItemId + ".js")
|
||||
.then(
|
||||
function (scriptWasLoadedNow) {
|
||||
if (scriptWasLoadedNow) {
|
||||
appendChildTocItems(tocItemId);
|
||||
fitTocHeightToViewport();
|
||||
return tocItemId;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function appendChildTocItems(parentTocItemId) {
|
||||
// get inner DIV of the container with subtopics
|
||||
var elmCont = document.getElementById("ci" + parentTocItemId);
|
||||
var childrenDefinitions = c[parentTocItemId]; //dynamically loaded from t_ID.js
|
||||
if (elmCont && childrenDefinitions && elmCont.children.length === 0) {
|
||||
for (i = 0; i < childrenDefinitions.length; i++) {
|
||||
appendTocNode(elmCont, childrenDefinitions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Selects (focus + highlight) specified TOC item
|
||||
* @param {string} tocItemId The ID of TOC item to select.
|
||||
*/
|
||||
function selectTocItem(tocItemId) {
|
||||
var linkContainer = document.getElementById(tocItemId);
|
||||
|
||||
var oldSelected = getDivWithClass(document.body, "toc-highlighted");
|
||||
if (oldSelected) {
|
||||
removeClassFromElement(oldSelected, "toc-highlighted");
|
||||
}
|
||||
addClassToElement(linkContainer, "toc-highlighted");
|
||||
|
||||
var links = linkContainer.getElementsByTagName("a");
|
||||
if (links.length > 0) {
|
||||
var link = links[0];
|
||||
//alert(link);
|
||||
//alert(link.innerHTML);
|
||||
if (!isElementVisibleY(link)) {
|
||||
link.scrollIntoView(true);
|
||||
}
|
||||
link.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function isElementVisibleY(el) {
|
||||
var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height;
|
||||
el = el.parentNode;
|
||||
// Check if bottom of the element is off the page
|
||||
if (rect.bottom < 0) return false;
|
||||
// Check its within the document viewport
|
||||
if (top > document.documentElement.clientHeight) return false;
|
||||
do {
|
||||
rect = el.getBoundingClientRect();
|
||||
if (top <= rect.bottom === false) return false;
|
||||
// Check if the element is out of view due to a container scrolling
|
||||
if ((top + height) <= rect.top) return false;
|
||||
el = el.parentNode;
|
||||
} while (el !== document.body);
|
||||
return true;
|
||||
}
|
||||
|
||||
// #endregion Main TOC
|
||||
|
||||
|
||||
// #region Internal (in-page) TOC
|
||||
|
||||
/**
|
||||
* The InternalTOC class representing a dynamic internal (in-page) TOC for the page sections.
|
||||
* */
|
||||
function InternalToc() {
|
||||
|
||||
/**
|
||||
* A single generated TOC item.
|
||||
* @typedef {Object} TocItem
|
||||
* @property {HTMLElement} listItem - The LI element of the TOC item.
|
||||
* @property {HTMLElement} anchor - The link element inside the LI.
|
||||
* @property {HTMLElement} target - The target element on the page.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The generated TOC items.
|
||||
* @type Array<TocItem>
|
||||
* */
|
||||
var tocItems;
|
||||
|
||||
// Factor of screen size that the element must cross
|
||||
// before it's considered visible
|
||||
var TOP_MARGIN = 0.0;
|
||||
var BOTTOM_MARGIN = 0.0;
|
||||
|
||||
// IE11 (used in CHM) doesn't have forEach, includes functions used in this class.
|
||||
// Add them.
|
||||
// NodeList.forEach
|
||||
if (window.NodeList && !NodeList.prototype.forEach) {
|
||||
NodeList.prototype.forEach = Array.prototype.forEach;
|
||||
}
|
||||
// Array.includes
|
||||
if (!Array.prototype.includes) {
|
||||
Object.defineProperty(Array.prototype, 'includes', {
|
||||
value: function (searchElement, fromIndex) {
|
||||
|
||||
if (this == null) {
|
||||
throw new TypeError('"this" is null or not defined');
|
||||
}
|
||||
|
||||
const o = Object(this);
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
const len = o.length >>> 0;
|
||||
|
||||
if (len === 0) {
|
||||
return false;
|
||||
}
|
||||
// tslint:disable-next-line:no-bitwise
|
||||
const n = fromIndex | 0;
|
||||
let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
|
||||
|
||||
while (k < len) {
|
||||
if (o[k] === searchElement) {
|
||||
return true;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
generateTOC(document.getElementById("internal-toc-container"));
|
||||
registerEventHandler(window, 'scroll', syncSelectedTocItems);
|
||||
|
||||
|
||||
/**
|
||||
* Generates the TOC from the section headings on the page.
|
||||
* @param {any} tocParent The parent element where the TOC will be added.
|
||||
*/
|
||||
function generateTOC(tocParent) {
|
||||
if (!tocParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pageContent = document.getElementById("mainBody");
|
||||
let headingsAll = pageContent.querySelectorAll('h2, h3, .section_heading, summary-info');
|
||||
let headings = [];
|
||||
let existingIDs = [];
|
||||
|
||||
// Preprocess the headings.
|
||||
headingsAll.forEach(function (heading) {
|
||||
if (heading.id) {
|
||||
existingIDs.push(heading.id);
|
||||
}
|
||||
|
||||
// Don't show 'Definition' for custom topics.
|
||||
let ignoreHeading = false;
|
||||
if (heading.tagName === "SUMMARY-INFO") {
|
||||
let codeMemberMetadata = pageContent.querySelector('div.metadata');
|
||||
if (codeMemberMetadata === null || codeMemberMetadata.textContent.trim().length=== 0) {
|
||||
ignoreHeading = true;
|
||||
}
|
||||
}
|
||||
if (!ignoreHeading) {
|
||||
headings.push(heading);
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure each heading has an ID.
|
||||
headings.forEach(function (heading) {
|
||||
if (!heading.id) {
|
||||
let id = heading.textContent.trim().toLowerCase().split(' ').join('-').replace(/[\!\@\#\$\%\^\&\*\(\)\:]/ig, '');
|
||||
if (id.length === 0) {
|
||||
id = "tocid";
|
||||
}
|
||||
id = generateUniqueID(id, existingIDs);
|
||||
heading.id = id;
|
||||
existingIDs.push(id);
|
||||
}
|
||||
});
|
||||
|
||||
// Create the TOC
|
||||
tocItems = [];
|
||||
if (headings.length > 0) {
|
||||
let tocHeading = document.getElementById("internal-toc-heading");
|
||||
if (tocHeading) {
|
||||
addClassToElement(tocHeading, "visible");
|
||||
}
|
||||
|
||||
let localizedDefinitionText = "Definition";
|
||||
let localizedHiddenElm = document.getElementById("internal-toc-definition-localized-text");
|
||||
if (localizedHiddenElm) {
|
||||
localizedDefinitionText = localizedHiddenElm.textContent;
|
||||
}
|
||||
|
||||
let olElm = document.createElement("ul");
|
||||
tocParent.appendChild(olElm);
|
||||
|
||||
headings.forEach(function (heading) {
|
||||
let text = heading.tagName === "SUMMARY-INFO" ? localizedDefinitionText : heading.textContent;
|
||||
let aElm = document.createElement("a");
|
||||
aElm.href = "#" + heading.id;
|
||||
aElm.innerHTML = text;
|
||||
|
||||
let liElm = document.createElement("li");
|
||||
liElm.appendChild(aElm);
|
||||
olElm.appendChild(liElm);
|
||||
|
||||
tocItems.push({
|
||||
listItem: liElm,
|
||||
anchor: aElm,
|
||||
target: heading
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
syncSelectedTocItems();
|
||||
}
|
||||
|
||||
|
||||
function generateUniqueID(id, existingIDs) {
|
||||
let newId = id;
|
||||
let i = 1;
|
||||
while (existingIDs.includes(newId)) {
|
||||
i++;
|
||||
newId = id + "_" + i;
|
||||
}
|
||||
return newId;
|
||||
}
|
||||
|
||||
|
||||
function syncSelectedTocItems() {
|
||||
var windowHeight = window.innerHeight;
|
||||
var MINIMUM_VISIBLE_PART = 5; // the minimum required visible part of a section to be considered as visible, in pixels
|
||||
|
||||
var previousItem = null;
|
||||
tocItems.forEach(function (item) {
|
||||
var targetBounds = item.target.getBoundingClientRect();
|
||||
|
||||
if (targetBounds.top < windowHeight - MINIMUM_VISIBLE_PART) {
|
||||
// The heading top is in the viewport or above it.
|
||||
item.listItem.classList.add('visible');
|
||||
}
|
||||
else {
|
||||
item.listItem.classList.remove('visible');
|
||||
}
|
||||
|
||||
// Correct the previous item, that could be marked as visible, but it isn't.
|
||||
if (previousItem && targetBounds.top < MINIMUM_VISIBLE_PART) {
|
||||
// prevous is not visible
|
||||
previousItem.listItem.classList.remove('visible');
|
||||
}
|
||||
previousItem = item;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// #endregion Internal (in-page) TOC
|
||||