I have a simple piece of code that loads headers and then changes some text in them. Recently an issue was reported where the headers are deleted. I've tracked it down to happening on loading the headers for these documents, and it appears they have 'Link to Previous' selected in the header options. I'm not sure why this would cause it to be deleted as the code up to that point makes no changes. Even this simple snippet causes the same issue.
Word.run(function (context) {
var sections = context.document.sections;
context.load(sections);
return context.sync().then(function() {
if (sections !== null) {
var headers = [];
for (var i = 0; i < sections.items.length; i++) {
var header = sections.items[i].getHeader('primary');
context.load(header);
headers.push(header);
}
context.sync().then(function() {
// when you get here all headers are deleted.
});
}
}).then(context.sync);
});
After some testing, what's really happening is that the LinkToPrevious setting is being removed. When that happens the content of the original header is removed from that header, which leaves nothing.
I could determine this by alternating the setting from section to section (on/off).
LinkToPrevious is not supported in the Office JS API that I can find, which may explain why the setting isn't being respected. I consider this a bug.
The only possibility to work around this that occurs to me would be to work over the Word Open XML for the headers.
Related
I've seen a couple answers but can't seem to figure out how to apply them.
I have a page that's two divs. A side nav div and a main div. On the page load, the js below loads up the html into the main div. The same function is used to jump around (via the nav) within the doc once loaded.
The problem is, there are also links within the HTML to the function since there are some self-referencing points, etc.
The side nav ones work fine, the ones within the HTML don't. I'm assuming it's a compiling issue of sorts, but I can't quite figure out how to compile it correctly.
Here's the JS:
Ctrler.loadPage = function(hash){
if(!hash){
var url = "filename.html";
var xhr= new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange= function() {
if (this.readyState!==4) return;
if (this.status!==200) return;
cur = this.responseText;
cur = cur.replace(/{{sitePath}}/g, jsPath.path);
document.getElementById('maindiv').innerHTML= cur;
$('#maindiv').html = this.responseText;
};
xhr.send();
}
else{
document.getElementById(hash).scrollIntoView();
window.scrollBy(0, -90);
}
}
EDIT: I changed the lines that populate the div to this:
$compile(cur)($scope);
$('#maindiv').append(cur);
but it still doesn't work. It loads the first time, but ng-clicks still don't work.
I figured it out.
I needed to compile $('#maindiv') after I added cur. Not cur
When you look at the documentation for office-js api's you have three header locations:
primary
firstpage
even
I would expect that setting a firstpage header would only show on the first page. However I doesn't seem to do anything. Am I missing something? The documentation is not very clear on this. In this sample only the primary is showing up.
private setHeader(): void {
Word.run((context) => {
let body = context.document.body;
let sections = context.document.sections;
context.load(sections, 'body/style');
return context.sync()
.then(() => {
let primary = sections.items[0].getHeader(Word.HeaderFooterType.primary);
primary.insertText('primary', Word.InsertLocation.replace)
let firstPage = sections.items[0].getHeader(Word.HeaderFooterType.firstPage);
firstPage.insertText('first page', Word.InsertLocation.replace);
context.sync()
.then(() => { },
((result: OfficeErrorMessage) => {
this.setErrorState(result);
})
);
;
});
});
}
ps. the sample is typescript.
very good question. if you set the headers with the API and then select the 'Different First Page' option on the Design ribbon of the header
you will see that effectively the header is there. The bad part is that we are fixing a bug to make sure its shown, basically we will expose those properties in the section object, we are planning to ship those as part of the next deliverable of the Word js API. Now, those options are actually on the file format (the odd and events on the settings package as <w:evenAndOddHeaders/> , and the 'Different first' a <w:titlePg> element is added on the section definition, so maybe inserting an OOXML can be a workaround for now.
Hope this helps!
I am using PhantomJS to create screenshots from arbitrary URLs. Before the screenshot is taken, I want to manipulate the page DOM to remove all drop-down menus, as PhantomJS renders them incorrectly in the top left-hand corner of the page (a known Phantom issue.)
I have a simple DOM script to do this with:
var selects = document.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
document.getElementsByTagName('select')[i].style.visibility="hidden";
}
This has been tested and works fine as stand-alone Javascript. It doesn't however work inside the PhantomJS code I am using to collect the screenshots (last part shown):
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
window.setTimeout(function () {
var selects = document.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
document.getElementsByTagName('select')[i].style.visibility="hidden";
}
page.render(output);
phantom.exit();
}, 200);
}
});
Some pages are still rendering with a select box in the wrong place. I'd appreciate help either solving the original PhantomJS rendering bug or hiding the drop-down menus in the DOM. Thanks.
Run it in the right context, i.e. inside the page with page.evaluate. There are many examples included with PhantomJS which demonstrate this, e.g. useragent.js.
This code doesn't work?
I used your cached selects variable in the for loop instead of re-selecting the elements from the DOM to improve performance.
var selects = document.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
selects[i].style.visibility="hidden";
}
I'm making a mobile-app using Phonegap and HTML. Now I'm using the google maps/places autocomplete feature. The problem is: if I run it in my browser on my computer everything works fine and I choose a suggestion to use out of the autocomplete list - if I deploy it on my mobile I still get suggestions but I'm not able to tap one. It seems the "suggestion-overlay" is just ignored and I can tap on the page. Is there a possibility to put focus on the list of suggestions or something that way ?
Hope someone can help me. Thanks in advance.
There is indeed a conflict with FastClick and PAC. I found that I needed to add the needsclick class to both the pac-item and all its children.
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
There is currently a pull request on github, but this hasn't been merged yet.
However, you can simply use this patched version of fastclick.
The patch adds the excludeNode option which let's you exclude DOM nodes handled by fastclick via regex. This is how I used it to make google autocomplete work with fastclick:
FastClick.attach(document.body, {
excludeNode: '^pac-'
});
This reply may be too late. But might be helpful for others.
I had the same issue and after debugging for hours, I found out this issue was because of adding "FastClick" library. After removing this, it worked as usual.
So for having fastClick and google suggestions, I have added this code in geo autocomplete
jQuery.fn.addGeoComplete = function(e){
var input = this;
$(input).attr("autocomplete" , "off");
var id = input.attr("id");
$(input).on("keypress", function(e){
var input = this;
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(37.2555, -121.9245),
new google.maps.LatLng(37.2555, -121.9245));
var options = {
bounds: defaultBounds,
mapkey: "xxx"
};
//Fix for fastclick issue
var g_autocomplete = $("body > .pac-container").filter(":visible");
g_autocomplete.bind('DOMNodeInserted DOMNodeRemoved', function(event) {
$(".pac-item", this).addClass("needsclick");
});
//End of fix
autocomplete = new google.maps.places.Autocomplete(document.getElementById(id), options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
//Handle place selection
});
});
}
if you are using Framework 7, it has a custom implementation of FastClicks. Instead of the needsclick class, F7 has no-fastclick. The function below is how it is implemented in F7:
function targetNeedsFastClick(el) {
var $el = $(el);
if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
return true;
}
So as suggested in other comments, you will only have to add the .no-fastclick class to .pac-item and in all its children
I was having the same problem,
I realized what the problem was that probably the focusout event of pac-container happens before the tap event of the pac-item (only in phonegap built-in browser).
The only way I could solve this, is to add padding-bottom to the input when it is focused and change the top attribute of the pac-container, so that the pac-container resides within the borders of the input.
Therefore when user clicks on item in list the focusout event is not fired.
It's dirty, but it works
worked perfectly for me :
$(document).on({
'DOMNodeInserted': function() {
$('.pac-item, .pac-item span', this).addClass('needsclick');
}
}, '.pac-container');
Configuration: Cordova / iOS iphone 5
I was hunting for an implementations of YUI AutoComplete and I came across this script from the site asklaila.com -
<script type="text/JavaScript">
YAHOO.example.ACJson = new function() {
this.oACDS = new YAHOO.widget.DS_XHR("/AutoComplete.do",
["Suggestions[0].Results","Name"]);
this.oACDS.queryMatchContains = true;
this.oACDS.scriptQueryAppend = "city=Mysore"; // Needed for YWS
function fnCallback(e, args) {
document.searchForm.where.focus();
acSelected = true;
return false;
}
this.oAutoComp = new YAHOO.widget.AutoComplete('what','whatContainer', this.oACDS);
this.oAutoComp.itemSelectEvent.subscribe(fnCallback);
this.oAutoComp.formatResult = function (oResultItem,sQuery) {
return oResultItem[0];
}
this.oAutoComp.queryDelay = 0;
this.oAutoComp.useIFrame = true;
this.oAutoComp.prehighlightClassName = "yui-ac-prehighlight";
this.oAutoComp.minQueryLength = 2;
this.oAutoComp.autoHighlight = false;
this.oAutoComp.textboxFocusEvent.subscribe(function() {
this.oAutoComp.sendQuery("");
});
this.oAutoComp.doBeforeExpandContainer = function(oTextbox, oContainer, sQuery, aResults) {
var pos = YAHOO.util.Dom.getXY(oTextbox);
pos[1] += YAHOO.util.Dom.get(oTextbox).offsetHeight + 2;
YAHOO.util.Dom.setXY(oContainer,pos);
return true;
};
}
</script>
It is implenting the YUI AutoComplete Dropdown. What I want to understand is what this
this.oACDS = new YAHOO.widget.DS_XHR("/AutoComplete.do", ["Suggestions[0].Results","Name"]);
does and its effects on code.
That's using an older version of YUI, but it is setting up a DataSource for the autocomplete to read from. This particular DataSource uses XHR to request information from the server to populate the autocomplete field.
"Autocomplete.do"
Is a relative URL that is being queried by the DataSource every time the autocomplete fires while the user is typing.
["Suggestions[0].Results","Name"]
Is the responseSchema that tells the DataSource how to parse the results from the request to the URL. It needs to know how to parse the data so that it can show the proper results.
this.oACDS = new YAHOO.widget.DS_XHR("/AutoComplete.do", ["Suggestions[0].Results","Name"]);
On every key press, it fetches a json response from the server, and uses it to populate the autocomplete dropdown. The json contains names to display only at this node, "Suggestions[0].Results" in the "name" field.
If you have any trouble, ask ahead. I wrote that piece of code for asklaila.com
I was hunting for implementations of
YUI Autocomplete and I came across
this script...
Why not take a look at YUI AutoComplete page for in-depth examples.
Yahoo! UI Library: AutoComplete