im trying to get a extension working which can grab the printed document through an event. I found the printerProvider Api. Afterwards i added the custom printer like that
chrome.printerProvider.onPrintRequested.addListener(function (job, status) {
console.log(job,status)
});
chrome.printerProvider.onGetPrintersRequested.addListener(
function ( resultCallback ) {
resultCallback( [{
id: '',
name: 'Custom Printer',
description: ''
}] );
}
);
Im struggling what id i have to fill in that i get the print dialog to work. I found this question which displays a way to add a network printer. (Google JavaScript API - Chrome.printerProvider: Printer id format)
Is there a way to get the PrintJob without actually printing to a specified printer in the id or if not is it possible to print to a pdf and get the PrintJob after saving (Windows 10 adds the "Microsoft Print to PDF Printer. But i dont know its id")?
I have found the answer to my question.
To be able to get the pdf content you have to use this code
chrome.printerProvider.onGetPrintersRequested.addListener(
function ( resultCallback ) {
resultCallback( [{
id: 'customprinter',
name: 'Custom Printer',
description: ''
}] );
}
);
chrome.printerProvider.onGetCapabilityRequested.addListener(function (printerId, resultCallback) {
console.log(printerId);
if(printerId == 'customprinter') {
resultCallback(capabilities);
}
});
For the capabilities variable you can use the example provided in the documentation https://developers.google.com/cloud-print/docs/cdd#cdd-example
When you set the capabilities a preview will be displayed and you are able to print.
In onPrintRequested you will then get the printjob.
Related
I use an angular 2 multiselect. When user clicks it an API gets called in the background and displays options in the drop-down. But as the API is taking time to give response the dropdown is showing as "No data available" and then showing the response when it recieves. How to change that default text to something like "Loading..." ?
Replace "No data available" with "Loading..." as default text. When the API is called and fetches response as you might be overriding dropdown options with response that will replace "Loading...". And If API fetches 0 response then you should replace with "No data available".
If you show "No data available" before just calling API then that means you are saying user that dropdown does not have any value but it brings value later. By this you are conveying wrong idea about the drop-down which is not aligned with UX what you need, If you agree.
Below solution is a hack, may be you want to rewrite as per requirement because I am assuming your code looks somewhat as below but I used along with solution:
html:
<ng-multiselect-dropdown
[placeholder]="text"
[data]="dropdownList"
[(ngModel)]="selectedItems"
[settings]="dropdownSettings"
(onSelect)="onItemSelect($event)"
>
</ng-multiselect-dropdown>
ts:
//Declare settings
this.dropdownSettings = {
singleSelection: false,
idField: 'id',
textField: 'text',
selectAllText: 'Select All',
unSelectAllText: 'UnSelect All',
noDataAvailablePlaceholderText: "Loading...",
itemsShowLimit: 3,
allowSearchFilter: true,
limitSelection: 2
};
}
onClick(){
// then api call here will replace the string most probably
}
There was a drop-down setting property called "noDataLabel"
which did the trick.. it's value is used when no data is available.
I was looking at discord.js documentation and I saw this :
.embeds
A list of embeds in the message - e.g. YouTube Player
Type: Array
"A list" :O ?
That mean it is possible to have several embeds in one message.
I have been looking for a way to do this, but I didn't find anything (I know there is another post on stack overflow about that, but it is inactive and unawsnered)
I took an old code channel.send(this.embed()); and tried to edit it so it send two embeds instead of just one.
this.embed() runs
{
var builder = new Discord.RichEmbed();
builder.setTitle(...);
...
return builder
}
First attempt was
channel.send(this.embed(), this.embed());
send [object Object] then the second embed*
channel.send("", this.embed(), this.embed());
send the first embed*
Then I looked at the doc more about .send :
.send([content] , [options])
Send a message to this channel.
blabla
Example 4
>// Send an embed with a local image inside
>channel.send('This is an embed', {
> embed: {
> thumbnail: {
> url: 'attachment://file.jpg'
> }
> },
> files: [{
> attachment: 'entire/path/to/file.jpg',
> name: 'file.jpg'
> }]
>})
> .then(console.log)
> .catch(console.error);
So I used that example and try to reproduce it for my case.
I tried a lot of differents syntax, and I won't post all the variations ^^'
But I want to show you these two :
channel.send("", {
{embed:this.embed(petit)},
{embed:this.embed(petit)}
}
);
SyntaxError: Unexpected token {
channel.send("", {
embed: [{this.embed(petit), this.embed(petit)}]
} );
SyntaxError: Unexpected token .
etc...
I feel like I get closer to the solution with the last attempts but I'm still missing something.
I really want to have all my embeds in one message, I know I can send them one by one but I don't want that :)
Also is there a maximum amount of embeds in a message ?
Thanks for reading, I hope I didn't made that much typos ^^
Nalfarvi
You can send multiples embedded messages with this syntax:
channel.send({
embed: {
// Your embedded message's content
},
embed: {
// Your second embedded message's content
}
})
I`m trying to insert a custom link to a special page in VisualEditor toolbar. See the image below.
See Image
I googled a lot but without success. Someone please give a path...
My answer is based on the following resources:
MediaWiki core JS doc (ooui-js)
VisualEditor JS doc (+ reading code of both repositories used for VE, mediawiki/extension/VisualEditor and VisualEditor)
Also, I'm pretty sure, that there is no documented way of adding a tool to the toolbar in VE, as far as I know. Although it's possible to add a tool to a group, which is already added, mostly used for the "Insert" tool group, like in Syntaxhighlight_GeSHi). There is, probably, a much easier or "better" way of doing this :)
First, VisualEditor provides a way to load additional modules (called plugins) when the main part of VE loads (mostly, when you click the "Edit" button). The modules needs to be registered via the global variable $wgVisualEditorPluginModules (or the equivalent in extension.json, if you're using the new extension registration). In your extension registration file, you should initialize a module (with your required script files to add the tool) and add it as a VE plugin.
Example PHP (old extension registration via PHP files):
// other setup...
$wgResourceModules['ext.extName.visualeditor'] = array(
'localBasePath' => __DIR__,
'remoteExtPath' => 'extName'
'dependencies' => array(
'ext.visualEditor.mwcore',
),
'scripts' => array(
'javascripts/ve.ui.ExtNameTool.js',
),
'messages' => array(
'extname-ve-toolname',
),
);
$wgVisualEditorPluginModules[] = 'ext.extName.visualeditor';
// other setup...
extension.json (new JSON-based extension registration):
// other setup...
"ResourceModules": {
"ext.geshi.visualEditor": {
"scripts": [
"javascripts/ve.ui.ExtNameTool.js"
],
"dependencies": [
"ext.visualEditor.mwcore"
],
"messages": [
"extname-ve-toolname"
]
}
},
"VisualEditorPluginModules": [
"ext.extName.visualeditor"
],
// other setup...
Now, if VE starts, it will load your module, named ext.extName.visualeditor in this example, with the script ve.ui.ExtNameTool.js. In this script, you can now do, what ever you want. As an example, this is a way to add a new module to the end of the toolgroup list in the toolbar:
Example of ve.ui.ExtNameTool.js:
( function () {
// create a new class, which will inherit ve.ui.Tool,
// which represents one tool
ve.ui.extNameTool = function extNameTool( toolGroup, config ) {
// parent constructor
ve.ui.extNameTool.super.apply( this, arguments );
// the tool should be enabled by default, enable it
this.setDisabled( false );
}
// inherit ve.ui.Tool
OO.inheritClass( ve.ui.extNameTool, ve.ui.Tool );
// every tool needs at least a name, or an icon
// (with the static property icon)
ve.ui.extNameTool.static.name = 'extname';
// don't add the tool to a named group automatically
ve.ui.extNameTool.static.autoAddToGroup = false;
// prevent this tool to be added to a catch-all group (*),
although this tool isn't added to a group
ve.ui.extNameTool.static.autoAddToCatchall = false;
// the title of the group (it's a message key,
// which should be added to the extensions i18n
// en.json file to be translateable)
// can be a string, too
ve.ui.extNameTool.static.title =
OO.ui.deferMsg( 'extname-ve-toolname' );
// onSelect is the handler for a click on the tool
ve.ui.extNameTool.prototype.onSelect = function () {
// show an alert box only, but you can do anything
alert( 'Hello' );
this.setActive( false );
}
// needs to be overwritten, but does nothing so far
ve.ui.extNameTool.prototype.onUpdateState = function () {
ve.ui.extNameTool.super.prototype.onUpdateState.apply( this, arguments );
}
// the tool needs to be registered to the toolFactory
// of the toolbar to be reachable with the given name
ve.ui.toolFactory.register( ve.ui.extNameTool );
// add this tool to the toolbar
ve.init.mw.Target.static.toolbarGroups.push( {
// this will create a new toolgroup with the tools
// named in this include directive. The naem is the name given
// in the static property of the tool
include: [ 'extname' ]
} );
} )();
After installing the extension in your LocalSettings.php and starting VE, you should see a new tool in the toolbar with the given name. Clicking it will show an alert box with content "Hello". Like written in the inline comments: In the click handler (onSelect) you can do whatever you want, e.g. open a link in a new tab, e.g. to a Special page. To get the link to a special page I would suggest to use mw.Title to get a localized namespace. For example:
var relativeUrl = mw.Title.newFromText( 'RecentChanges', -1 ).getUrl();
The first parameter of mw.Title.newFromText() is the name of the page, the second parameter is the ID of the namespace (-1 is the default for special pages and should always work).
I hope that helps!
I am not sure I understand your question entirely. It is as simple as selecting some text, clicking the chain icon, then clicking the External Link tab and pasting your link there.
I'm struggeling with DOJO 1.8 and Datagrid. I would like to put a filteringSelect into a Datagrid cell. The widget should be fed by a Store. The store is fed by an AJAX request and works find. Also the select widget shows up, but it is empty. There's neither a value nor an option to see in the browser:
The Code for the Store:
// AJAX REQUEST TO GET PROJECTS AND SAVE AS STORE
require(['dojo/request', 'dojo/data/ItemFileReadStore'], function(request, ItemFileReadStore){
request('project/json/getprojects', {
handleAs: 'json'
}).then(function(json){
var projectStore = new ItemFileReadStore({data: {'identifier':'id', 'label':'label', 'items': json}});
});
The JSON I retrieve looks like this:
[{"id":2,"name":"Bilder-App","customer":"Company A","label":"Company A >> Bilder-App"},{"id":8,"name":"Zeiterfassung","customer":"Company B","label":"Company B >> Zeiterfassung"}]
The goal is that the select-box shows the "label" field visually and saves "id" to the store/grid.
Here's the code of the grid_layout for the cell:
{field: "project_id", name: "Kunde/Projekt", type: dojox.grid.cells._Widget, widgetClass: dijit.form.Select, widgetProps: {store: projectStore, searchAttr: "label"} },
Is anyone able to help me with that?
MANY THANKS!
AFX
Here is the working formatter:
// PROJECT-ID FORMATTER
function formatProjectId(value, index){
var item = projectStore.get(value);
var label = item['label'];
return label;
}
However, there's one slight problem: Right when I selected the item in the select box it shows the id in the field. When I leave the field it gets formatted correctly.
Does anyone know how to solve this?
OK!
I was able to find a solution.
First of all, I changed to Memory-Store, since I figured out that the ItemFileReadStore wasn't working correctly.
I read somewhere, that you need to require the 'dijit/form/FilteringSelect' specifically. So I did that.
So my field in the layout variable looks like this:
{field: "project_id", name: "Kunde/Projekt", type: dojox.grid.cells._Widget, widgetClass: dijit.form.FilteringSelect, widgetProps: {searchAttr: "id", labelAttr: "label", store: projectStore}},
My Store has an array of data consisting of the fields 'id' and 'label'...so it gave the field those attributes! And BOOOOM...it works!
Now I have to add a formatter-function to format the displayed IDs onces they were edited.
Posting about this soon!
Have a good one,
AFX
I am having a horrible time understanding Sencha Touch 2's architecture. I'm finding even the most basic things I do in other language and frameworks to be incredibly painful.
Currently, I just want to do a standard Master/Detail view. I load a store into a list view and would like to click on each list item to slide in a detail view. Since my initial list view can contain quite a lot of items, I'm only loading a little bit of the data with this method in my controller:
viewUserCommand: function(list, record) {
// console.log(record);
var profileStore = Ext.getStore("Profiles");
profileStore.setProxy({
url: 'http://localhost:8000/profile/' + record.data.user_id
});
profileStore.load();
// console.log(profileStore);
Ext.Viewport.animateActiveItem(Ext.getCmp('profileview'), this.slideLeftTransition);
}
First, modifying the url property for each tap event seems a bit hacky. Isn't there a way to specify "this.id" or something along those lines, and then pass that to my store? Or would that require loading the entire DB table into an object?
I can console.log the return from this method and it's exactly what I want. How do I populate the detail view? I've tried utilizing a DataView component, but it doesn't show any data. The examples on sencha's website are fairly sparse, and relatively contextless. That means that even copying and pasting their examples are likely to fail. (Any examples I've tried using Ext.modelMgr.getModel() have failed.)
I know it's partly that this framework is new and I'm probably missing a huge gaping hole in my understanding of it, but does anyone have any clue?
Would suggest you check out the docs, there's an example of loading a single model:
http://docs.sencha.com/touch/2-0/#!/api/Ext.data.Model
Ext.define('User', {
extend: 'Ext.data.Model',
config: {
fields: ['id', 'name', 'email'],
proxy: {
type: 'rest',
url : '/users'
}
}
});
//get a reference to the User model class
var User = Ext.ModelManager.getModel('User');
//Uses the configured RestProxy to make a GET request to /users/123
User.load(123, {
success: function(user) {
console.log(user.getId()); //logs 123
}
});