I'm writing a protractor script that need to upload a JPEG image. I could click on the upload button which opens up a windows file selector. But, then I need to write the path to a file in that File Selector dialog using protractor.
But, i have no idea how it works. I tried just typing the path using sendKeys and it doesn't work so far.
Anyone have an idea how to do this?
Thanks. :)
Try my answer in "How can I control the windows File Selector using protractor".
If you need a quick solution try the following solution:
// set file detector
var remote = require('../../node_modules/protractor/node_modules/selenium-webdriver/remote');
browser.setFileDetector(new remote.FileDetector());
var fileToUpload = '../sample.txt';
var absolutePath = path.resolve(__dirname, fileToUpload);
var fileElem = element(by.css('input[type="file"]'));
// Unhide file input
browser.executeScript("arguments[0].style.visibility = 'visible'; arguments[0].style.height = '1px'; arguments[0].style.width = '1px'; arguments[0].style.opacity = 1", fileElem.getWebElement());
fileElem.sendKeys(absolutePath);
// take a breath
browser.driver.sleep(100);
// click upload button
element(by.css('button[data-ng-click="uploadFile(file)"]')).click(); // does post request
[settingsEditProfile_page.settingsEditProfile_UploadImageButton()][1].isDisplayed().then(function () {
helperUtil.addStep("User redirected to Edit Profile page"); settingsEditProfile_page.settingsEditProfile_UploadImageButton().sendKeys(absolutePath).then(function () {
helperUtil.addStep("User clicked on upload button and uploaded new image");
browser.driver.sleep(3000);
settingsEditProfile_page.settingsEditProfile_Save().click().then(function () {
helperUtil.addStep("User clicked on SAVE button");
});
});
});
uploadFile: async (locator, filepath) => {
absolutePath = path.resolve(filepath);
click(locator);
element(by.css('input[type="file"]')).sendKeys(absolutePath);
await sleep(10000, "wait to close window");
await closePopup();
},
Related
My current project requires a file download. The file is auto generated and has an unfriendly name when it's saved, so we are changing the file name to something easier to read on download.
For example if a user downloads a file called 324343242342.pdf we change it to Lesson1.pdf or something for the one that's saved on their computer.
I'm having some trouble with ie11 with this. I know that the download attribute doesn't work on ie11, so for that sake we are using blobs and things are working fine for download purposes across browsers, but I'm not sure how to change the name of the file in ie11.
In all other browsers I just do <a href="#" :download="new_file_name"> to call a small file name calculating method in the vue component, but this doesn't work for ie11 because the "download" attribute doesn't work there.
Anyone have any idea how to go about editing that name in ie11 as well? I'm only finding answers for fixing the download functionality in general, nothing about setting a file name.
Thank you!
You have to do something similar to https://github.com/kennethjiang/js-file-download/blob/master/file-download.js
function downloadFile (data, filename, mime) {
const blob = new Blob([data], { type: mime || 'application/octet-stream' })
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// For IE
window.navigator.msSaveBlob(blob, filename)
} else {
// For other browsers
const blobURL = window.URL.createObjectURL(blob)
const tempLink = document.createElement('a')
tempLink.style.display = 'none'
tempLink.href = blobURL
tempLink.setAttribute('download', filename)
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank')
}
document.body.appendChild(tempLink)
tempLink.click()
document.body.removeChild(tempLink)
window.URL.revokeObjectURL(blobURL)
}
}
I have a Suitelet rendering a PDF from various record types which do not currently have Advanced PDF functionality.
Everything works fine when I file.save() the finished PDF, but I would like the option to open the PDF in the browser without saving to the file cabinet first.
Currently, the action part of the script is this:
var templateFile = config.getValue({fieldId:'custrecord_extpdf_template_xml'});
var templateHTML = file.load({id: templateFile}).getContents();
var renderer = render.create();
renderer.templateContent = templateHTML;
renderer.addRecord('record',rec);
renderer.addRecord('config',config);
if (SAVETORECORD) {
var PDF = renderer.renderAsPdf();
PDF.folder = config.getValue({fieldId: 'custrecord_extpdf_temp_folder'});
PDF.name = param.rectype + param.id + '.pdf';
var fid = PDF.save();
var attachitem = record.attach({
record: { type: 'file', id: fid },
to: { type: param.rectype, id: param.id }
})
context.response.write(file.load({id:fid}).url )
}
else {
var PDF = renderer.renderAsPdf();
PDF.name = param.rectype + param.id + '.pdf';
context.response.writeFile(PDF,false)
}
When the variable SAVETORECORD is true, the PDF renders nicely, and opens in a new tab, attaches to the record, and is saved to the file cabinet.
However, when SAVETORECORD is false, a new window opens but is BLANK.
The Suitelet is called from a custom button trigger with the following code:
var response = https.get({url: suiteletURL });
if (response.body) window.open(response.body,'_blank');
window.location.reload(true);
I've tried context.response.writeFile(PDF,false) and context.response.writeFile(PDF,true) but get the same result.
What am I missing here?
After sleeping on it, I figured what I'd done wrong.
To save the PDF, the code stays as is.
To open in the browser without saving, I just needed to open the SuiteLet URL rather than the response.body from the button script:
if (SAVERECORD) {
var response = https.get({url: suiteletURL });
if (response.body) window.open(response.body,'_blank');
}
else {
window.open(suiteletURL,'_blank');
}
window.location.reload(true);
I need to change the "title" for each document shown in ICN Viewer, dynamically, at runtime. I'll read the new viewer tab title from the document properties
ENVIRONMENT: ICN 2.0.3 CM8.5 WAS 8.5.5
CODE SO FAR:
I found a PARTIAL solution by hooking "ecm.model.desktop, onChange":
aspect.after(ecm.model.desktop, 'onChange', function() {
var contentViewer = dijit.byId('contentViewer');
if (contentViewer) {
var viewerTabTitleDef = new ViewerTabTitleDef ();
contentViewer.mainTabContainer.getChildren().forEach(function(child) {
viewerTabTitleDef.changeTitle(viewerTabTitleDef.self,
child.controlButton, child.contentViewerPane.viewerItem.item);
});
...
I was able to extend this for subsequent documents opened in the same viewer, and optimized by "removing()" the handler after this initial call. Here is the complete code:
var kill = aspect.after(ecm.model.desktop, 'onChange', function() {
var contentViewer = dijit.byId('contentViewer');
// "contentViewer" will be "unknown" unless viewer invoked
console.log('onChange: contentViewer', contentViewer);
if (contentViewer) {
console.log("new ViewerTabTitleDef()...");
kill.remove();
var viewerTabTitleDef = new ViewerTabTitleDef ();
contentViewer.mainTabContainer.getChildren().forEach(function(child) {
// For initially opened tabs
console.log('initially opened: child', child);
viewerTabTitleDef.changeTitle(viewerTabTitleDef.self, child.controlButton, child.contentViewerPane.viewerItem.item);
});
aspect.after(contentViewer.mainTabContainer, 'addChild', function(child) {
// For tabs added after the viewer was opened
console.log('subsequently opened: child', child);
viewerTabTitleDef.changeTitle(viewerTabTitleDef, child.controlButton, child.contentViewerPane.viewerItem.item);
}, true);
} // end if contentViewer
}); // end aspect.after(onChange desktop)
CURRENT PROBLEM:
Q: How can I change the label for a split tab (either vertical or horizontal)?
So far, I have NOT been able to find any event for any ICN/ECM widget or object variable that I can trigger on.
Thank you in advance!
===============================================
ADDENDUM:
Many thanks to Ivo Jonker, for his suggestion to modify the widget prototype's
"getHtmlName()" method. It worked!
Specifically:
I'm invoking this code from an ICN plugin. I set event handlers in my plugin's base .js file, but it actually gets invoked in the new, separate viewer window.
The original prototype looked like this:
getHtmlName: function() {
var methodName = "getHtmlName";
this.logEntry(methodName);
var displayName = this.item.getDisplayValue("{NAME}");
if (displayName == "") {
displayName = this.item.name;
}
var htmlName = entities.encode(displayName);
this.logExit(methodName);
return htmlName;
},
Per Ivo's suggestion, I overrode the prototype method like this:
myPluginDojo.viewerTabTitleDef = viewerTabTitleDef;
...
ecm.widget.viewer.model.ViewerItem.prototype.getHtmlName = function () {
console.log("NEW getHtmlName()...");
var displayName = myPluginDojo.viewerTabTitleDef.getTitle(this.item);
return displayName;
};
If i understand you correctly, you want to show a different tab-title (instead of the document title) in the navigator viewer whenever a doc is opened?
How about this:
Every document you open in the viewer is wrapped in a ecm.widget.viewer.model.ViewerItem which exposes the getHtmlName that returns the name used in the tab.
Your solution would be to implement your own getHtmlName.
Unfortunately though, the ViewerItem is constructed in the ecm.widget.viewer.ContentViewer#_open and then passed to the ecm.widget.viewer.ContentViewer#_openTab. So you'll either violate best practice by mingling with IBM private method's, or you'll go for a generic approach and just replace the ecm.widget.viewer.model.ViewerItem.prototype.getHtmlName
I'm trying to figure out how to make a Google Apps Script deployed as a web app download a PDF that's generated on a click. It almost works, but the resulting file isn't valid. I can't figure out if it's an encoding issue or something else.
In Apps Script the code looks simple:
function makePDF() {
...
var pdfBlob = doc.getAs('application/pdf');
return Utilities.base64Encode(pdfBlob.getBytes());
}
In the browser, there's a click handler:
function clickHandler(ev) {
ev.preventDefault();
google.script.run
.withSuccessHandler(function(data) {
var pdf = new Blob([window.atob(data)]);
var href = window.URL.createObjectURL(pdf);
var link = document.querySelector('#hiddenLink');
link.href = href;
link.click();
})
.makePDF();
}
Any suggestions?
Thanks!
I figured it out, so posting the answer if anyone else is trying to pass a PDF from Apps Script to the client javascript. It's all much simpler than I had made it.
Rather than messing around with base64 encodings, just pass back the bytes array:
function makePDF() {
...
var pdfBlob = DocumentApp.openById('1234').getAs('application/pdf');
return pdfBlob.getBytes();
}
Now, on the client side, construct a new Blob from an ArrayBuffer. That's easy too:
function clickHandler(ev) {
google.script.run
.withSuccessHandler(function(data) {
var arr = new Uint8Array(data);
var blob = new Blob([arr.buffer], {type: 'application/pdf'});
var obj_url = window.URL.createObjectURL(blob);
var hiddenLink = document.getElementById('hiddenPDFLink');
hiddenLink.setAttribute('href', obj_url);
hiddenLink.setAttribute('download', 'filename.pdf');
hiddenLink.click();
})
.makePDF();
}
And that's it! Hope someone else finds this helpful.
I assume that your makePDF function is doing some other stuffs/Calculation and at the end you need that document to be downloaded to local computer.
What you can do is inside success handler
var link = document.querySelector('#hiddenLink');
link.href = "https://docs.google.com/feeds/download/documents/export/Export?id=**TheIdOfDocumenToBeDownloaded**&exportFormat=pdf";
link.click();
It will then give you a prompt to save document on to local computer.
i developing sample android application in Titanium. on home window(app.js) it has some buttons ,now what i want is on the click of each button app.js(home window) must call another javascript file (they will create new window of their own.
but.addEventListener('click', function(e){
call another .js file which will open new window
})
will appreciate some guidance
that's not so hard. Incl. params.
First create your other .js file and create a function as follows.
Another .js File:
exports.createNewWindow(params) {
var window = Ti.UI.createWindow ({
// ... Your stuff with your params
});
return window;
}
Than you can call this function as follows:
First .js File
var window = require("pathToYouAnotherFile.js").createNewWindow({title:"xyz"});
window.open();
If you want you can call the window.open() in the "another.js" file.
Have fun.
You should learn Alloy. It will help you properly structure your app, as you have asked.
http://projects.appcelerator.com/alloy/docs/Alloy-bootstrap/index.html
I handled this by raising an event from one JS file to another. Take a look at Ti.App.fireEvent('event',data) to fire the event and Ti.App.addEventListener to receive the event.
but.addEventListener('click', function(e){
var newwin=Ti.UI.createWindow({url:'another.js'});
newwin.open();
});
Its a simple event handler in which we are creating and opening a windows and opening after that.Url is the file to the desired window.
Simple.Cheers!!
var All = require('ui/common/All');
Tree = require('ui/common/Tree');
EBOM = require('ui/common/E-BOM');
MBOM = require('ui/common/M-BOM');
SBOM = require('ui/common/S-BOM');
//create object instance
var self = Ti.UI.createWindow({
title:'Products',
exitOnClose:true,
navBarHidden:true,
backgroundColor:'#ffffff',
/////////////////////////////////////////////////////////////////////////////
activity: {
onCreateOptionsMenu: function(e) {
var menu = e.menu;
var menuItem = menu.add({ title: "C-BOM", icon: 'Arrow-Hover.jpg' });
//menuItem.setIcon("Arrow-Hover.jpg");
menuItem.addEventListener("click", function(e) {
var all = new All();
self.add(all);
});
......................
.....................
..........................