I have an Office Addin and am trying to update the title of the document on desktop. i have tried 2 diffrent ways and none of them works on hte desktop. It works fine on word online but not on the desktop.
Word.run(async (context) => {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log(newTitle.value);
context.document.properties.title = newTitle.value;
});
This code works online but not on the desktop. I have also tried doing doing it in this way.
Office.context.document.customXmlParts.getByNamespaceAsync("http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
function (resultCore) {
var xmlPart = resultCore.value[0];
xmlPart.getNodesAsync('*/*', function (nodeResult) {
for (var i = 0; i < nodeResult.value.length; i++) {
var node = nodeResult.value[i];
console.log("BaseName: ")
console.log(node.baseName);
if (node.baseName === "title") {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log("title that you entered: " + newTitle.value);
console.log(node);
node.setNodeValueAsync(newTitle.value, { asyncContext: "StateNormal" }, function (data) { });
}
}
});
});
Does anyone know why it doesn't work or have some other solution to my problem?
The following code works for me, including on desktop. Note that you have to await the Word.run. Also, you have to load the title and then sync to make sure you have changed the title on the actual document and not merely in the proxy object in your task pane code.
await Word.run(async (context) => {
var newTitle = document.getElementById("inputTitle") as HTMLInputElement;
console.log(newTitle.value);
context.document.properties.title = newTitle.value;
const myProperties = context.document.properties.load("title");
await context.sync();
console.log(myProperties.title);
});
Related
I have connected MongoDB to my discord.js code and have made a setwelcome command as per-server data so that each server can customize their own welcome message. Everything works great, I just want to know if there is any way that I can make the message appear as an embed? Here's the code:
//importing all the needed files and languages
const mongo = require('./mongo')
const command = require('./command')
const welcomeSchema = require('./schemas/welcome-schema')
const mongoose = require('mongoose')
const Discord = require('discord.js')
mongoose.set('useFindAndModify', false);
//my code is inside this export
module.exports = (client) => {
//this next line is for later
const cache = {}
command(client, 'setwelcome', async (message) => {
const { member, channel, content, guild } = message
//checking to see that only admins can do this
if (!member.hasPermissions === 'ADMINISTRATOR') {
channel.send('You do not have the permission to run this command')
return
}
//simplifying commands
let text = content
//this is to store just the command and not the prefix in mongo compass
const split = text.split(' ')
if (split.length < 2) {
channel.send('Please provide a welcome message!')
return
}
split.shift()
text = split.join(' ')
//this is to not fetch from the database after code ran once
cache[guild.id] = [channel.id, text]
//this is to store the code inside mongo compass
await mongo().then(async (mongoose) => {
try {
await welcomeSchema.findOneAndUpdate({
_id: guild.id
}, {
_id: guild.id,
channelId: channel.id,
text,
}, {
upsert: true
})
} finally {
mongoose.connection.close()
}
})
})
//this is to fetch from the database
const onJoin = async (member) => {
const { guild } = member
let data = cache[guild.id]
if (!data) {
console.log('FETCHING FROM DATABASE')
await mongo().then( async (mongoose) => {
try {
const result = await welcomeSchema.findOne({ _id: guild.id })
cache[guild.id] = data = [result.channelId, result.text]
} finally {
mongoose.connection.close()
}
})
}
//this is to simplify into variables
const channelId = data[0]
const text = data[1]
/*this is where the message sends on discord. the second of these 2 lines is what I want embedded
which is basically the welcome message itself*/
const channel = guild.channels.cache.get(channelId)
channel.send(text.replace(/<#>/g, `<#${member.id}>`))
}
//this is to test the command
command(client, 'simjoin', message => {
onJoin(message.member)
})
//this is so the command works when someone joins
client.on('guildMemberAdd', member => {
onJoin(member)
})
}
I know how to usually make an embed, but I'm just confused at the moment on what to put as .setDescription() for the embed.
Please advise.
If you just want to have the message be sent as an embed, create a MessageEmbed and use setDescription() with the description as the only argument. Then send it with channel.send(embed).
const embed = new Discord.MessageEmbed();
embed.setDescription(text.replace(/<#>/g, `<#${member.id}>`));
channel.send(embed);
By the way, if you are confused about how to use a specific method you can always search for the method name on the official discord.js documentation so you don’t have to wait for an answer here. Good luck creating your bot!
I would like to insert a watermark into a Word document using Office.js. I am able to insert the watermark DRAFT using the sample code from: https://github.com/OfficeDev/Word-Add-in-JS-Watermark/blob/master/WatermarksManagerWeb/Home.js. The sample code places the watermark all on pages.
I am interested in a simpler solution than the one below that places the watermark only on the first page. Thank you.
(function () {
"use strict";
var messageBanner;
// The initialize function must be run each time a new page is loaded.
Office.initialize = function (reason) {
$(document).ready(function () {
$('#createWM').click(insertWaterMark);
$('#deleteWM').click(removeWM);
$('#txtWM').val("DRAFT");
});
};
function insertWaterMark() {
Word.run(function (ctx) {
var mySections = ctx.document.sections;
ctx.load(mySections);
// ctx.document.body.insertOoxml(mywatermark, "end");
return ctx.sync().then(function () {
var myWatermark = getWM($('#txtWM').val());
var myHeader = mySections.items[0].getHeader("primary");
var myRange = myHeader.insertOoxml(myWatermark, "replace");
var myCC = myRange.insertContentControl();
myCC.title = "myTempCC";
myCC.appearance = "hidden";
return ctx.sync();
});
}).catch(function (e) {
app.showNotification(e.message, e.description);
});
}
function getWM(text) {
var mywatermark = "<?xml version=\"1.0\" standalone=\"yes\"?>\r\n<?mso-application progid=\"Word.Document\"?>\r\n<pkg:package xmlns:pkg=\"http://schemas.microsoft.com/office/2006/xmlPackage\"> ... THE REST OF THE OPENXML content for watermark ...</pkg:package>\r\n";
return (mywatermark.replace("CONFIDENTIAL", text));
}
Update: I think I have an idea how to get the watermark on the first page. I implemented the solution, but it doesn't show the watermark. Please look at my code and let me know if you see anything wrong with it.
var mySections = ctx.document.sections;
ctx.load(mySections);
return ctx.sync().then(function () {
var myWatermark = getWM("DRAFT");
var myHeader = mySections.items[0].getHeader(Word.HeaderFooterType.firstPage);
mySections.items[0].headerFooterFirstPageDifferent = true;
var myRange = myHeader.insertOoxml(myWatermark, "replace");
var myCC = myRange.insertContentControl();
myCC.title = "myTempCC";
myCC.appearance = "hidden";
return ctx.sync();
I looked in the documentation, here on stackoverflow, on github and in several places but I couldn't find any solution that would help me to insert a watermark in the page header.
But after a few days of difficulty, I was testing all possible methods and combinations of use until I managed to understand how to insert the watermark. And it's simpler than I thought. Too bad this isn't in Microsoft Docs.
return Word.run( (context) => {
context.document.sections.getFirst().getHeader().insertParagraph('WaterMark', Word.InsertLocation.start);
context.sync();
});
I figured out how to insert a real watermark into the body of a document.
private async insertWatermark(): void {
await Word.run(async (context) => {
const paragraphs = context.document.sections.getFirst().getHeader(Word.HeaderFooterType.primary).paragraphs;
paragraphs.load("$none");
await context.sync();
const newParagraph = paragraphs.getLastOrNullObject();
let contentControl = newParagraph.insertContentControl();
contentControl.insertOoxml(this.addWatermarkText("My Watermark Text"), Word.InsertLocation.end);
await context.sync();
}
private addWatermarkText(text: string = "My Watermark"): string {
const watermark: string = 'Watermark Content HERE';
return watermark.replace("WATERMARK", text);
}
Get Watermark content in this link for replace this code snippet 'Watermark Content HERE'
I'm a Java developer and new to protractor. I'm trying to iterate through a dynamic web table in a web page and trying to find out a particular user name and open his profile. Once I open his profile, I want my test method to stop execution and return. But the return statement doesn't work and the for loop still runs. Could anyone please help me with this? Below is my method.
searchUser() {
// Iterate through the user listing table
browser.driver.findElement(by.css('.slds-max-medium-table--stacked-horizontal')).then(function (table) {
table.findElement(by.tagName('tbody')).then(function (tbody) {
tbody.findElements(by.tagName('tr')).then(function (rows) {
for (var i = 0; i < rows.length; i++) {
rows[i].findElements(by.tagName('td')).then(function (cols) {
cols[1].getText().then(function (user) {
if (user == "ADAM SMITH") {
// found user, open his profile
cols[1].click();
return;
}
});
});
}
// user not found in the current page. Click on next page and continue search
element(by.xpath("//*[#id='main']/div/app-users-profile/users-listing/form/div[2]/div/div/div/div[2]/div/button")).click();
browser.sleep(3000);
var currentPage = new LoginPage();
currentPage.searchUser();
});
});
});
}
I try to make as less differences as I can.
async function searchUser () {
let result = false;
while (!result) {
const table = browser.$('.slds-max-medium-table--stacked-horizontal');
const tbody = table.$('tbody');
const rows = tbody.$$('tr');
await rows.map(async (row) => {
const column = row.findElements(by.tagName('td')).get(1);
const name = await column.getText();
if (name === 'ADAM SMITH') {
await column.click();
result = true;
}
});
if (!result) {
await element(by.xpath("//*[#id='main']/div/app-users-profile/users-listing/form/div[2]/div/div/div/div[2]/div/button")).click();
await browser.sleep(3000);
const currentPage = new LoginPage();
await currentPage.searchUser();
}
}
}
I need some help with Javascript to get fancybox working with SCP. The following solution has not worked for me although I'm aware I'm missing some fundamental code. The first product image works perfectly opening the fancybox lightbox but once you select from the configurable dropdowns it changes the image which then does not call the lightbox and opens in the browser.
SCP advice is:
To fix, it's often just a matter of editing the showFullImageDiv function in the scp_product_extension.js file: Change evalScripts to true if it's not already, and possibly you'll also need to remove the code which exists in a few places which looks like: product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
I tried this but it's not just a simple matter of removing "product_zoom..." my understanding is that fancybox needs to be called replace this line of code.
Original:
Product.Config.prototype.showFullImageDiv = function(productId, parentId) {
var imgUrl = this.config.ajaxBaseUrl + "image/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
var destElement = false;
var defaultZoomer = this.config.imageZoomer;
prodForm.select('div.product-img-box').each(function(el) {
destElement = el;
});
if(productId) {
new Ajax.Updater(destElement, imgUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
//Product.Zoom needs the *image* (not just the html source from the ajax)
//to have loaded before it works, hence image object and onload handler
if ($('image')){
var imgObj = new Image();
imgObj.src = $('image').src;
imgObj.onload = function() {product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint'); };
} else {
destElement.innerHTML = defaultZoomer;
product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint')
}
}
});
} else {
destElement.innerHTML = defaultZoomer;
product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
}
};
I know I need to call fancybox in the below locations but not sure how to go about it. From what I understand fancybox is called on pageload so not sure imgObj.onload will even work?
Product.Config.prototype.showFullImageDiv = function(productId, parentId) {
var imgUrl = this.config.ajaxBaseUrl + "image/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
var destElement = false;
var defaultZoomer = this.config.imageZoomer;
prodForm.select('div.product-img-box').each(function(el) {
destElement = el;
});
if(productId) {
new Ajax.Updater(destElement, imgUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
//Product.Zoom needs the *image* (not just the html source from the ajax)
//to have loaded before it works, hence image object and onload handler
if ($('image')){
var imgObj = new Image();
imgObj.src = $('image').src;
imgObj.onload = CALL FANCYBOX
} else {
destElement.innerHTML = defaultZoomer;
CALL FANCYBOX
}
}
});
} else {
destElement.innerHTML = defaultZoomer;
CALL FANCYBOX
}
};
Unfortunately my javascript is very basic and any help on what I need to add would be gratefully received. I found a few posts with the same issue but no solution.
Thanks
I have an existing node.js app where users have a library of files that are stored with GridFS. Each user has their own library. I would like to make the library mountable with WebDAV so that a user could manage their library from their desktop.
I have seen jsDAV used to access the filesystem but it is not clear how to extend it for use with a virtual file system. I found gitDav but it is not clear how to use it.
Is this even possible without starting from scratch?
I was looking to use jsDAV to make some resources available through WebDAV. Failing to find a working example, I studied the comments in the source and wrote one myself. jsDAV is a port from a PHP library. The Sabre manual is useful guide in general. One thing to remember is that since we're in an asynchronous environment, functions that return the results in PHP might have to invoke a callback function instead. This usually happens when the operation in question involves reading from the disk. The first parameter to the callback will always be an error object, which should be null when all goes well.
'use strict';
var crypto = require('crypto');
var jsDAV = require("jsDAV/lib/jsdav");
var jsDAVLocksBackendFS = require("jsDAV/lib/DAV/plugins/locks/fs");
var jsDAVFile = require("jsDAV/lib/DAV/file");
var jsDAVCollection = require("jsDAV/lib/DAV/collection");
var jsExceptions = require("jsDAV/lib/shared/exceptions");
var VirtualFile = jsDAVFile.extend(
{
initialize: function(name, buffer) {
this.name = name;
this.buffer = buffer;
},
getName: function() {
return this.name;
},
get: function(callback) {
callback(null, this.buffer);
},
put: function(data, type, callback) {
callback(new jsExceptions.Forbidden("Permission denied to change data"));
},
getSize: function(callback) {
callback(null, this.buffer.length);
},
getETag: function(callback) {
var shasum = crypto.createHash('sha1');
shasum.update(this.buffer);
var etag = '"' + shasum.digest('hex') + '"';
callback(null, etag);
},
getContentType: function(callback) {
callback(null, 'text/plain');
}
});
var VirtualDirectory = jsDAVCollection.extend(
{
initialize: function(name, children) {
this.name = name;
this.children = children;
},
getChildren: function(callback) {
var list = [];
for (var name in this.children) {
list.push(this.children[name]);
}
callback(null, list);
},
getChild: function(name, callback) {
var child = this.children[name];
if (child) {
callback(null, child);
} else {
callback(new jsExceptions.NotFound("File not found"));
}
},
childExists: function(name, callback) {
var exists = (this.children[name] !== undefined);
callback(null, exists);
},
getName: function() {
return this.name;
}
});
var children = {};
for (var i = 1; i <= 10; i++) {
var name = 'file' + i + '.txt';
var text = 'Hello world, #' + i;
children[name] = VirtualFile.new(name, new Buffer(text, 'utf8'));
}
var grandchildren = {};
for (var i = 66; i <= 99; i++) {
var name = 'beer' + i + '.txt';
var text = i + ' bottles of beer';
grandchildren[name] = VirtualFile.new(name, new Buffer(text, 'utf8'));
}
children['folder'] = VirtualDirectory.new('folder', grandchildren);
var root = VirtualDirectory.new(null, children);
var options = {
node: root,
locksBackend: jsDAVLocksBackendFS.new(__dirname + "/data")
};
var port = 8000;
jsDAV.createServer(options, port);
It looks like jsDAV is the only option. It is a port of a PHP library and it is not setup in such a way that you can use it like a normal node.js module. I found a few examples of server types that others have created to connect it with dropbox and couchdb.
I am now working on a server type that will work more like you would expect a node.js module to work. The next step will be making it play nice with npm. You can see my fork here.