retriving data from Content control using Word Api - ms-word

I'm developing a Word Add-in (Word API + Office.js) where i am working with content controls, i am try to check whether control is blank
i am using the below code for this functionality
function callPromise() {
return new Promise(function (resolve, reject) {
var MadatoryFieldsList = ["Control1", "Control2", "Control3"];
$.each(MadatoryFieldsList, function (index, element) {
Word.run(function (context) {
var contentControls = context.document.contentControls.getByTag(element).getFirst();
contentControls.load('text');
return context.sync().then(function () {
var text = contentControls.text;
if (text == "") {
//document.getElementById('lblMandatory').innerText += element + " is Mandatory" + " ";
mandatoryflag = "False";
}
if (index === MadatoryFieldsList.length - 1) resolve();
})
});
});
});
}
this works fine when i create the content control manually from developer tab in word document ... but if i copy the same from different document or load it from database in the form of OOXML it is not able to fetch the controls.
please let me know if i am missing something

Related

How to create customized Add Comment in Word-Addins Taskpane?

I am creating an MS-Word Add-ins for Word for mac and I have to create a custom comment section with a task pane so I have created one textbox and create a button on click on button comment is added to that selected text.
I find many articles but don't work for me so that I attach a sample code below.
HTML File
<div class="padding">
<textarea id="areaDiv"></textarea>
<button id="addComment">Add Comment</button>
<div id="errorDiv"></div>
</div>
**JS File**
Office.onReady(function () {
// Office is ready
$(document).ready(function () {
// The document is ready
// Use this to check whether the API is supported in the Word client.
if (Office.context.requirements.isSetSupported('WordApi', '1.1')) {
// Do something that is only available via the new APIs
$('#addComment').click(addComment);
$('#supportedVersion').html('This code is using Word 2016 or later.');
}
else {
// Just letting you know that this code will not work with your version of Word.
$('#supportedVersion').html('This code requires Word 2016 or later.');
}
});
});
// Function that writes to a div with id='message' on the page.
function addComment() {
Office.context.document.getSelectedDataAsync(Office.CoercionType.Text,
{ valueFormat: "unformatted", filterType: "all" },
function (asyncResult) {
var error = asyncResult.error;
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
write('');
}
else {
var range = asyncResult.value;
write(range);
}
});
}
function onError(error) {
$('#errorDiv').text(error.name + ' ' + error.code + ': ' + error.message);
}
function write(range) {
$('#errorDiv').text(range);
var text = $("#areaDiv").val();
if (range != null && range != "" && text != null && text != "") {
$('#errorDiv').text(range + " " + text);
var document = Office.context.document.properties.comments;
document.add(range, text);
$("#areaDiv").val("");
}
}
Here there is no error but there is an issue of no comment is set the selected text and not goes in the catch block.
If anyone has an idea about this then it helps me a lot.

Get all bookmark IDs from Word Document

I want to scan an entire document containing text with the styles Heading 1, Heading 2, normal text and several bullet points / other text (which is basically a tech report). After scanning I want to extract bookmarks assigned to "Heading 2" elements, which also act as sub heading titles within the report.
getBookmarks() is defined in the Preview / Beta API which works if my cursor is placed on the "Heading 2" element, as seen below:
async function getBookmarks() {
Word.run(function(context) {
var range = context.document.getSelection();
var bkmrk = range.getBookmarks(true, true);
return context.sync().then(function() {
console.log("The bookmarks read from the document was: " + bkmrk.value);
});
}).catch(function(error) {
console.log("Error: " + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log("Debug info: " + JSON.stringify(error.debugInfo));
}
});
}
I've managed to scan the entire document and obtain the "style" attribute as well, as seen from the example code on API documentation:
async function getParagraphAll() { await Word.run(async (context) => {
// Gets the complete sentence (as range) associated with the insertion point.
let paragraphs = context.document.body.paragraphs
paragraphs.load("text, style");
await context.sync();
// Expands the range to the end of the paragraph to get all the complete sentences.
let completeParagraph = paragraphs.items[0]
.getRange()
.expandTo(
context.document
.getSelection()
.paragraphs.getFirst()
.getRange("End")
)
paragraphs.load("text, style, hyperlink");
await context.sync();
for (let i = 0; i < paragraphs.items.length; i++) {
console.log(paragraphs.items[i].style);
//let range = paragraphs.items[i].getRange() - Why is this not working ?
//let bkmrk = range.getBookmarks(true, false) - This doesnt get me the bookmark while its in
//the loop scanning the entire document. Is it because it fails on "Normal" style?
// Should I filter out "Normal" and only run "getBookmarks" on "Heading" style ?
console.log(paragraphs.items[i].style);
} }); }
I've made the reference to Libraries available in the preview API link: https://appsforoffice.microsoft.com/lib/beta/hosted/office.js
I'm struggling to understand why I can get the bookmark at cursor level but when I want to get it for the entire document, it just displays
do context.sync() before loading any property. There is no need for
load.

Get current Work item data in VSTS Extension

I am want to create a VSTS Extension for TFS 2015 Update 3 and I want to start slow. I want to create a custom action that shows the Id and the Title of the current Work Item in one pop up window.
I have been reading the tutorials but I still don't get it.
I used this example from GitHub:
var showPropertiesMenuProvider = (function () {
"use strict";
return {
showPropertiesInDialog: function(properties, title) {
VSS.getService("ms.vss-web.dialog-service").then(function (dialogSvc) {
var extInfo = VSS.getExtensionContext();
var contibution = VSS.getContribution();
var dialogOptions = {
title: title || "Properties",
width: 800,
height: 600,
buttons: null
};
var contributionConfig = {
properties: properties
};
dialogSvc.openDialog(extInfo.publisherId + "." + extInfo.extensionId + "." + "contextForm", dialogOptions, contributionConfig);
});
},
execute: function(actionContext) {
this.showPropertiesInDialog(actionContext);
}
};
}());
VSS.register("showProperties", function (context) {
return showPropertiesMenuProvider;
});
which gives me a lot of information but I still can't extract the data I need.
Any ideas?
Thanks in advance!

How to use the numericRefinementList to set allowed distances?

I would like to be able to use the numericRefinementList to allow users to pick the distance from themselves an item can be? This would be using the IP geo-location feature or inputting the geo-location from browser if available.
Less than 50km
50 - 100km
100 - 150km
More than 150km
https://community.algolia.com/instantsearch.js/documentation/#numericrefinementlist
This is unfortunately not something you can do with the numericRefinementList but you can probably build a custom widget setting the aroundRadius depending on the link you've clicked on:
function radiusList(options) {
if (!options.container) {
throw new Error('radiusList: usage: radiusList({container, ...})');
}
var $container = $(options.container);
if ($container.length === 0) {
throw new Error('radiusList: cannot select \'' + options.container + '\'');
}
return {
init: function(args) {
// event delegation: set the aroundRadius of the underlying link
$(document).on('click', '.radius-link', function(e) {
e.preventDefault();
args.helper.setQueryParameter('aroundRadius', +$(this).data('radius'));
args.helper.search();
});
},
render: function(args) {
// FIXME: display the list of radius links
var html = '<ul>';
html += '<li>< 100km</li>';
html += '</ul>';
$container.html(html);
}
};
}
And then you use it with:
search.addWidget(radiusList({container: '#my-radius-list'}));

Handle selected event in autocomplete textbox using bootstrap Typeahead?

I want to run JavaScript function just after user select a value using autocomplete textbox bootstrap Typeahead.
I'm searching for something like selected event.
$('.typeahead').on('typeahead:selected', function(evt, item) {
// do what you want with the item here
})
$('.typeahead').typeahead({
updater: function(item) {
// do what you want with the item here
return item;
}
})
For an explanation of the way typeahead works for what you want to do here, taking the following code example:
HTML input field:
<input type="text" id="my-input-field" value="" />
JavaScript code block:
$('#my-input-field').typeahead({
source: function (query, process) {
return $.get('json-page.json', { query: query }, function (data) {
return process(data.options);
});
},
updater: function(item) {
myOwnFunction(item);
var $fld = $('#my-input-field');
return item;
}
})
Explanation:
Your input field is set as a typeahead field with the first line: $('#my-input-field').typeahead(
When text is entered, it fires the source: option to fetch the JSON list and display it to the user.
If a user clicks an item (or selects it with the cursor keys and enter), it then runs the updater: option. Note that it hasn't yet updated the text field with the selected value.
You can grab the selected item using the item variable and do what you want with it, e.g. myOwnFunction(item).
I've included an example of creating a reference to the input field itself $fld, in case you want to do something with it. Note that you can't reference the field using $(this).
You must then include the line return item; within the updater: option so the input field is actually updated with the item variable.
first time i've posted an answer on here (plenty of times I've found an answer here though), so here's my contribution, hope it helps. You should be able to detect a change - try this:
function bob(result) {
alert('hi bob, you typed: '+ result);
}
$('#myTypeAhead').change(function(){
var result = $(this).val()
//call your function here
bob(result);
});
According to their documentation, the proper way of handling selected event is by using this event handler:
$('#selector').on('typeahead:select', function(evt, item) {
console.log(evt)
console.log(item)
// Your Code Here
})
What worked for me is below:
$('#someinput').typeahead({
source: ['test1', 'test2'],
afterSelect: function (item) {
// do what is needed with item
//and then, for example ,focus on some other control
$("#someelementID").focus();
}
});
I created an extension that includes that feature.
https://github.com/tcrosen/twitter-bootstrap-typeahead
source: function (query, process) {
return $.get(
url,
{ query: query },
function (data) {
limit: 10,
data = $.parseJSON(data);
return process(data);
}
);
},
afterSelect: function(item) {
$("#divId").val(item.id);
$("#divId").val(item.name);
}
Fully working example with some tricks. Assuming you are searching for trademarks and you want to get the selected trademark Id.
In your view MVC,
#Html.TextBoxFor(model => model.TrademarkName, new { id = "txtTrademarkName", #class = "form-control",
autocomplete = "off", dataprovide = "typeahead" })
#Html.HiddenFor(model => model.TrademarkId, new { id = "hdnTrademarkId" })
Html
<input type="text" id="txtTrademarkName" autocomplete="off" dataprovide="typeahead" class="form-control" value="" maxlength="100" />
<input type="hidden" id="hdnTrademarkId" />
In your JQuery,
$(document).ready(function () {
var trademarksHashMap = {};
var lastTrademarkNameChosen = "";
$("#txtTrademarkName").typeahead({
source: function (queryValue, process) {
// Although you receive queryValue,
// but the value is not accurate in case of cutting (Ctrl + X) the text from the text box.
// So, get the value from the input itself.
queryValue = $("#txtTrademarkName").val();
queryValue = queryValue.trim();// Trim to ignore spaces.
// If no text is entered, set the hidden value of TrademarkId to null and return.
if (queryValue.length === 0) {
$("#hdnTrademarkId").val(null);
return 0;
}
// If the entered text is the last chosen text, no need to search again.
if (lastTrademarkNameChosen === queryValue) {
return 0;
}
// Set the trademarkId to null as the entered text, doesn't match anything.
$("#hdnTrademarkId").val(null);
var url = "/areaname/controllername/SearchTrademarks";
var params = { trademarkName: queryValue };
// Your get method should return a limited set (for example: 10 records) that starts with {{queryValue}}.
// Return a list (of length 10) of object {id, text}.
return $.get(url, params, function (data) {
// Keeps the current displayed items in popup.
var trademarks = [];
// Loop through and push to the array.
$.each(data, function (i, item) {
var itemToDisplay = item.text;
trademarksHashMap[itemToDisplay] = item;
trademarks.push(itemToDisplay);
});
// Process the details and the popup will be shown with the limited set of data returned.
process(trademarks);
});
},
updater: function (itemToDisplay) {
// The user selectes a value using the mouse, now get the trademark id by the selected text.
var selectedTrademarkId = parseInt(trademarksHashMap[itemToDisplay].value);
$("#hdnTrademarkId").val(selectedTrademarkId);
// Save the last chosen text to prevent searching if the text not changed.
lastTrademarkNameChosen = itemToDisplay;
// return the text to be displayed inside the textbox.
return itemToDisplay;
}
});
});