Issue:
I've been trying to figure out how to use the "position" configuration settings of the Aurelia-Dialog plugin on my Aurelia based website, but I can't figure it out cannot find a single example on all of the Internet of Things.
A very vague bit of documentation can be found here:
http://aurelia.io/hub.html#/doc/article/aurelia/dialog/latest/dialog-basics/5
For those of you not wishing to visit the link, for "position" it says:
Position - a callback that is called right before showing the modal with the signature: (modalContainer: Element, modalOverlay: Element) => void. This allows you to setup special classes, play with the position, etc... If specified, centerHorizontalOnly is ignored. (optional)
I've tried everything from attempting to add code directly to the plugin configuration in main.js:
plugin('aurelia-dialog', config => {}
.plugin('aurelia-dialog', config => {
config.useDefaults();
//config.settings.position = ;
})
To attempting to use it as an argument my dialogService.open function:
showMessage(message, title = 'Message', options = ['Ok'], dismissable = false) {
return this.dialogService.open({ viewModel: TestModal,
model: { message, title, options },
overlayDismiss:
dismissable,
position: function(stuff){ modal, modalOverlay} });
My Question:
How do I actually use the position setting, and if my function(stuff){modal, overlay} format is correct, how do I actually pass a modal and an overlay to this function?
I'm pretty much at a dead-end on this so any help would be useful.
Thanks in Advance.
In the constructor of your dialog class, you need to inject the DialogController, then define the callback function.
import { DialogController } from "aurelia-dialog";
#inject(DialogController)
export class YourDialog {
constructor(private controller: DialogController) {
this.controller.settings.position = (modalContainer: Element, modalOverlay: Element) => {
let container = modalContainer;
let overlay = modalOverLay;
};
}
}
Related
Is there a way to only show part of a document, or in monacos case of a model, while still getting intellisense for the whole document?
I only want a user to edit a part of a document, but the user should be able to get the right contextual intellisense.
It would be best for my usecase to hide the uneditable sections, but deactivating them would also be ok.
In case this is not possible, is there any embedded editor that can do this, or can this be achived by modifying the language server?
Monaco editor loads every line as a container under a section with the class name "view-lines". Once the editor content has loaded, set "display: none" to the corresponding container for each line that you want to hide.
Implementation: https://jsfiddle.net/renatodc/s6fxedo2/
let value = `function capitalizeFirstLetter(string) {
\treturn string.charAt(0).toUpperCase() + string.slice(1);
}
$(function() {
\tlet word = "script";
\tlet result = capitalizeFirstLetter(word);
\tconsole.log(result);
});
`
let linesToDisable = [1,2,3];
let editor = monaco.editor.create(document.getElementById('container'), {
value,
language: 'javascript',
theme: 'vs-dark',
scrollbar: {
vertical: "hidden",
handleMouseWheel: false
},
scrollBeyondLastLine: false
});
// onLoad event for Monaco Editor: https://github.com/Microsoft/monaco-editor/issues/115
let didScrollChangeDisposable = editor.onDidScrollChange(function() {
didScrollChangeDisposable.dispose();
setTimeout(function() {
$(".monaco-editor .view-lines > div").each(function(i) {
if(linesToDisable.includes(i+1)) {
$(this).css("display","none");
$(this).css("pointer-events","none");
}
});
},1000);
});
Scrolling from Monaco will render the lines again and break the implementation. To prevent this, disable the scrolling feature in Monaco, set a fixed height for the editor container, and use the browser or a parent container to scroll instead.
If you use the arrow keys 'up' or 'down' to navigate to the hidden content, the cursor will still work, and typing will break the implementation. You might be able to use the editor's onKeyDown event to prevent this.
If you're looking for a break-proof implementation, I would suggest loading Monaco editor only with the portion of the document that you wish to edit. Then extend the completion provider (Intellisense) as shown in this example: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
monaco.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems: function(model, position) {
return {
suggestions: [
{
label: "capitalizeFirstLetter",
kind: monaco.languages.CompletionItemKind.Method,
documentation: "Capitalize the first letter of a word",
insertText: "capitalizeFirstLetter("
}
]
};
}
});
monaco.editor.create(document.getElementById("container"), {
value: `$(function() {
\tlet word = "script";
\tlet result = capitalizeFirstLetter(word);
\tconsole.log(result);
});
`,
language: "javascript"
});
Use an AST parser like Esprima to get the identifiers from your source document, and plug these into the suggestions array.
I have implemented a custom math plugin and integrated it into ck5. this plugin will convert math latex to image equation and I'm able to render the converted math equation image into a ck5 editor using the below code.
editor.model.change(writer => {
const imageElement = writer.createElement('image', {
src: data.detail.imgURL
});
editor.model.insertContent(imageElement, selection);
});
Still here everything is working fine. when i'm trying to store original latex equation value in image tag as custom attribute (attribute name is data-mathml ). It strips out custom attributes.
So I have gone through the documentation and tried but was not able to add the custom attribute.
Below is my code :
class InsertImage extends Plugin {
init() {
const editor = this.editor;
const view = editor.editing.view;
const viewDocument = view.document;
// Somewhere in your plugin's init() callback:
view.addObserver( ClickObserver );
editor.ui.componentFactory.add('insertImage', locale => {
const view = new ButtonView(locale);
view.set({
label: 'Add Equations',
withText: true,
tooltip: true
});
// Callback executed once the image is clicked.
this.listenTo(view, 'execute', () => {
openModel();
});
return view;
});
window.addEventListener('setDatatoCK', function(data){
const selection = editor.model.document.selection;
editor.model.change( writer => {
const imageElement = writer.createElement( 'image', {
src: data.detail.imgURL,
'data-mthml': data.detail.latexFrmla,
} );
editor.model.insertContent( imageElement, selection );
} );
})
this.listenTo( editor.editing.view.document, 'click', ( evt, data ) => {
if ( data.domEvent.detail == 2 ) {
editorToPopupdoubleClickHandler( data.domTarget, data.domEvent );
evt.stop();
}
}, { priority: 'highest' } );
}
};
I want to add multiple attributes to the image tag. What should I do to add multiple attributes?
(Note: I'm able to create a new custom tag (tag named "math") with multiple attributes but not for image tag)
Please help me with this. this blocker for me.
Methods tried:
In order to achieve this, I have created one custom tag with multiple attributes and append image tags under this custom tag. It's working fine as expected but I want to add multiple attributes to image tag not with the custom tag.
✔️ Expected result
❌ Actual result
📃 Other details
Browser: Google Chrome Version 78.0.3904.108 (Official Build) (64-bit)
OS: macOS Mojave 10.14.6
CKEditor version: CKEditor 5
Installed CKEditor plugins: ckeditor5-editor-classic,ckeditor5-image,ckeditor5-essentials,ckeditor5-basic-styles,ckeditor5-core,ckeditor5-ui
Hope you've already found a solution to this answer. After spending several hours on searching a solution to a similar problem, I've made it working. See below:
// you have to import the insertImage fn to be able to override default imageinsert fn
import { insertImage } from '#ckeditor/ckeditor5-image/src/image/utils.js'
// this method HAVE to be automatically called when ckeditor is onready.
// You can add custom eventlistener or on the html tag just define listener:
// in Vue2 we used to do like this: <ckeditor #ready="someFnOnCkEditorReadyState()" />
someFnOnCkEditorReadyState() {
// as for img tag the options supported by ckeditor is very limited, we must define our properties to extend the used schema
editor.model.schema.extend('image', { allowAttributes: ['data-mathml'] })
// add conversion for downcast
editor.conversion.for('downcast').add(modelToViewAttributeConverter('data-mathml'))
// add conversion for upcast
editor.conversion.for('upcast').attributeToAttribute({
view: {
name: 'image',
key: 'data-mathml',
},
model: 'data-mathml',
})
}
// then you have to implement your custom image insert method
// from now on this will be your default insertImage fn
// this modification might require other modifications for example to add a custom image browser button to the toolbar
otherFnToInsertImg() {
insertImage(editor.model, {
src: image.url,
'data-mathml': 'here comes the magic',
})
}
Hope it helps someone to save some hours. ;)
My Problem:
I am trying to click options in a dropdown with Nightwatch, using sections in page objects. I'm not sure if it's a problem with the section declaration or i'm missing something scope-related. Problem is that it finds the element as visible, but when it tries to click it will throw error that it cannot locate it using recursion.
What could i try to do to fix this issue using sections?
In the test:
var myPage = browser.page.searchPageObject();
var mySection = searchPage.section.setResults;
// [finding and clicking the dropdown so it opens and displays the options]
browser.pause (3000);
browser.expect.section('#setResults').to.be.visible.before(1000);
myPage.myFunction(mySection, '18');
In the page object:
var searchKeywordCommands = {
myFunction: function (section, x) {
section.expect.element('#set18').to.be.visible.before(2000);
if (x == '18') section.click('#set18');
//[...]
};
module.exports = {
//[.. other elements and commands..]
sections: {
setResults: {
selector: '.select-theme-result', //have also tried with '.select-content' and '.select-options' but with the same result
elements: {
set18: '.select-option[data-value="18"]',
set36: '.select-option[data-value="36"]' //etc
}}}}
Here is my source code:
When i run this piece of core, it seems to find the section, finds the element visible (i also can clearly see that it opens the dropdown and shows the options) but when trying to click any option, i get the error: ERROR: Unable to locate element: Section[name=setResults], Element[name=#set18]" using: recursion
Here is the full error:
My attempts:
I have tried to declare that set18 selector as an individual element instead of inside of the section and everything works fine this way, but won't work inside of the section. I have also tried all the selectors available to define the section's selector, but it won't work with any of them.
This is what i am doing with(LOL)
I assume steps would be (find dropbox - click dropbox - select value).
var getValueElement = {
getValueSelector: function (x) {
return 'li[data-value="'+ x + '"]';
}
};
module.exports = {
//[.. other elements and commands..]
sections: {
setResults: {
commands:[getValueElement],
selector: 'div[class*="select-theme-result"', //* mean contains,sometime class is too long and unique,also because i am lazy.
elements: {
setHighlight:'li[class*="select-option-highlight"]',
setSelected:'li[class*="select-option-selected"]',
//set18: 'li[data-value="18"]',
//set36: 'li[data-value="36"]'
// i think getValueFunction is better,what if you have 100+ of set.
}}}}
In your test
var myPage = browser.page.searchPageObject();
var mySection = searchPage.section.setResults;
// [finding and clicking the dropdown so it opens and displays the options]
mySection
.click('#dropboxSelector')
.waitForElementVisible('#setHighlight',5000,false,
function(){
var set18 = mySection.getValueElement(18);
mySection.click(set18);
});
Ps:in my case(i think your case also), dropbox or any small third-party js framework which is used many times in your web app, so better create a different PageObject for it,make pageObject/section is simple as possible.
I'm trying to create my own lightbox script where I can pass the variables (title, description, itemtype, itemid, etc.) in clean formatting like this (inspired by fancybox):
myFunction({
title: "My title",
description: "My description"
});
Clicking on a certain element prepends some HTML to a div with jQuery.
I have adapted a piece of code I found on Stackoverflow and "kind of" understand the code. The top function has not been changed and worked before I edited the bottom code, to that I added click(function() { } because in the example the code was executed on pageload.
However, when I click my H1 element the firebug console tells me ReferenceError: popup is not defined
This is my Javascript:
$(document).ready(function() {
(function ($) {
$.fn.popup = function (options) {
var settings = $.extend({
title: function (someData) {
return someData;
},
description: function (someData) {
return someData;
},
}, options);
$("#content").prepend(
"<div style=\"position:fixed;top:0;left:0;width:100%;height:100%;background:#FFFFFF;\">\
<h1>"+ settings.title +"</h1>\
<p>" + settings.description +"</p>\
</div>"
);
};
}(jQuery));
$(".openbox1").click(function() {
popup({
title: "Title 1",
description: "Description 1"
});
}));
$(".openbox2").click(function() {
popup({
title: "Title 2",
description: "Description 2"
});
}));
});
This is my HTML
<div id="content">
<h1 class="openbox1">open box 1</h1>
<h1 class="openbox2">open box 2</h1>
</div>
A. Wolff commented that I need to execute the function like this:
$(".openbox1").click(function() {
$(this).popup({
...
});
});
This fixed it, thanks!
First off, what you did, and I hope this helps:
// This, of course is same as "document.onload"
// Don't confuse it with "window.onload"
// wich will wait till WHOLE dom is loaded to run any script
$(document).ready(function() {
(function ($) {
// This is, in essence, the start of a jQuery plugin
// This is often referred to as the "quick and dirty setup"
// as it's a direct call to add a method to jQuery's
// element object. Meaning it can be recalled as
// $(element).popup().
// This should not be confused with $.popup = function
// which would just add a method to jQuery's core object
$.fn.popup = function (options) {
var settings = $.extend({
...
}(jQuery));
$(".openbox1").click(function() {
// here is where your issue comes in
// as previously noted, you did not create a
// method named "popup".
// you added a method to jQuery's Element Object
// called "popup".
// This is why `$(this).popup` works and
// plain `popup` does not.
// You're inside an "event" asigned to any element
// having class name `openbox1`. Thus, any call
// in here to `this`, will reference that element
popup({
Secondly, a different example of how to write it. I won't say better because, even if I say my way is better, it wouldn't make your "corrected" way wrong. In Javascript, as the old saying goes, There's more than one way to skin a cat.
My Example:
// Notice I'm adding this plugin BEFORE the document load.
// This means, you could easily add this to a file and load it
// in script tags like any other Javascript,
// as long as it's loaded AFTER jquery.
(function($) {
// this ensures that your plugin name is available and not previously added to jQuery library
if (!$.popup) {
// this also provides us "variable scope" within to work in
// here begin adding the plugin to jQuery
// I started with $.extend, so it can be added to the jQuery library and used in traditional format
// $.popup('element selector', { options })
// as well as the element.action format we'll add later
// $.(element selector).popup({ options })
// This should help give you a good idea of the whole of what all is going on
$.extend({
popup: function() {
var ele = arguments[0], // this is our jQuery element
args = Array.prototype.slice.call(arguments, 1); // this gets the rest of the arguments
// this next step is useful if you make the traditional call `$.popup(this, { options })`
if (!(ele instanceof jQuery)) ele = $(ele);
// now we have total control! Bwahahha!
// Fun aside, here is where it's good to check if you've already asigned this plugin
// if not, then make some "marker", so you can recall the element plugin and comment an
// action instead of reinitializing it
if (!ele.data('popup')) $.popup.init(ele, args);
else {
// at this point, you would know the element already has this plugin initialized
// so here you could change an initial options
// like how with jQueryUI, you might would call:
// $(element).popup('option', 'optionName', value)
}
return ele;
}
});
// here is where we add the $(element selector).popup method
// this simply adds the method to the element object
// If you don't fully understand what's going on inside (as I explain below),
// just know that it's some "fancy footwork" to pass the method onto our initial
// method creation, $.popup
$.fn.extend({
popup: function(/*no need for parameter names here as arguments are evaluated inside and passed on to initial method*/) {
// set this element as first argument to fit with initial plugin method
var args = [$(this)];
// if there are arguments/params/options/commands too be set, add them
if (arguments.length) for (x in arguments) args.push(arguments[x]);
// pass through jquery and our arguments, end result provides same arguments as if the call was:
// $.popup($(element), options)
return $.popup.apply($, args);
}
});
// This next part is not seen in many plugins but useful depending on what you're creating
$.popup.init = function(ele, opt) {
// here is where we'll handle the "heavy work" of establishing a plugin on this element
// Start with setting the options for this plugin.
// This means extending the default options to use any passed in options
// In the most simple of cases, options are passed in as an Oject.
// However, that's not always the case, thus the reason for this being
// a continued array of our arguments from earlier.
// We'll stick with the simplest case for now, your case, that the only options are an
// Object that was passed in.
// using the extend method, with true, with a blank object,
// allows us to added the new options "on top" of the default ones, without changing the default ones
// oh and the "true" part just tells extend to "dig deep" basically (multideminsional)
if (opt && typeof opt[0] == 'object') opt = $.extend(true, {}, $.popup.defaults, opt[0]);
var par = opt.parent instanceof jQuery ? opt.parent : $('body'),
tit = opt.title,
des = opt.description,
// this last one will be the wrapper element we put everything in
// you have this in yours, but it's written in a very long way
// this is jQuery simplified
wrap = $('<div />', { style: 'position:fixed;top:0;left:0;width:100%;height:100%;background:#FFFFFF;' }),
// much like the previous element, cept this is where our title goes
head = $('<h1 />', { text: tit }).appendTo(wrap),
content = $('<p />', { text: des }).appendTo(wrap);
$(par).append(wrap);
// finally, add our marker i mentioned earlier
ele.data('popup', opt);
// just adding the following cause i noticed there is no close
// fyi, i would change this plugin a little and make an actial "open" command, but that's another tutorial
var closer = $('<span />', { text: '[x]', style: 'cursor:pointer;position:absolute;bottom:1em;right:1em;' });
wrap.append(closer);
closer.click(function(e) { ele.data('popup', false); wrap.remove(); });
};
$.popup.defaults = { // establish base properties here that can be over-written via .props, but their values should never truly change
'parent': undefined, // added this to keep it dynamic, instead of always looking for an element ID'd as content
title: '',
description: ''
};
}
})(jQuery);
// the following is basically jQuery shorthand for document.ready
$(function() {
// i think you get the rest
$(".openbox1").on('click', function(e) {
$(this).popup({
title: "Title 1",
description: "Description 1",
parent: $("#content")
});
})
$(".openbox2").on('click', function(e) {
$(this).popup({
title: "Title 2",
description: "Description 2",
parent: $("#content")
});
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="content">
<h1 class="openbox1">open box 1</h1>
<h1 class="openbox2">open box 2</h1>
</div>
I wanted to hide some issue link outward & inwards strings of Link type from the Link Issues Popup Window using java script.
I have tried using java script but I am not getting the popup screen from the java script.
Please see the screenshot below :
Can anyone tell me how can I get this popup screen in the java script?
Is there any other method to hide this?
Thanks & Regards,
Renuka.
To hide the clone issue link every page:
edit the file system-webresources-plugin.xml (should be at /atlassian-jira/WEB-INF/classes/), and add to <web-resource key="jira-fields"> this code:
<resource type="download" name="myScript.js" location="/includes/jira/field/script.js">
<param name="source" value="webContextStatic"/>
</resource>
than, on /includes/jira/field/myScript.js write this:
AJS.$(document).ready(function() {
if (AJS.$("#link-type option[value*='clon']").size() > 0) {
// will work even when right clicking on More
// Actions->Link & open it into a new window
AJS.$("#link-type option[value*='clon']").remove()
} else if (AJS.$("#link-issue").size() > 0) {
// will work in case the link menu showing via popup
AJS.$("#link-issue").click(function(){
// wait for the popup to show, and remove the clone options
setTimeout(function (){
AJS.$("#link-type option[value*='clon']").remove();
}, 300);
});
}
});
restart Jira and it that it!
The script attaches a function to the link-menu opening, than gives the menu 0.3 seconds to load, and removes the unwanted items. If it doesn't work well for you, try to raise the timeout from 300 to 500-1000.
On jira 4, run instead:
AJS.$("#issue-link-link-type option[value*='clon']").remove();
The previous solution has an issue:
It will only work when clicking the "Link Issue"-Menu-Item.
When I use the Point (.)-Shortcut-Menu, it won't remove the issue types.
I have established the following solution:
JS-Binding-Part:
AJS.$(document).ready(function() {
JIRA.bind(JIRA.Events.NEW_CONTENT_ADDED, function(e, context, reason) {
hideIssueLinkTypes();
});
});
JS-Backing-Function:
function hideIssueLinkTypes() {
var apiURL = "/rest/scriptrunner/latest/custom/getHiddenLinkTypes"
$.getJSON( apiURL, {
}).done(function( objectData ) {
$.each( objectData, function( i, item ) {
var issueLinkType = item.issueLinkType[0];
AJS.$("#link-type option[value='"+issueLinkType.inwardDescription+"']").remove();
AJS.$("#link-type option[value='"+issueLinkType.outwardDescription+"']").remove();
});
});
}
Scriptrunner-REST-Endpoint:
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.transform.BaseScript
import com.atlassian.jira.issue.link.DefaultIssueLinkTypeManager
import com.atlassian.jira.issue.link.IssueLinkTypeManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.properties.ApplicationProperties
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
#BaseScript CustomEndpointDelegate delegate
String HIDDEN_IDENT="[hidden]"
getHiddenLinkTypes(httpMethod: "GET") { MultivaluedMap queryParams, String body ->
def appProperties = ((ApplicationProperties) ComponentAccessor.getComponentOfType(ApplicationProperties.class));
def appClonersLinkTypeName = appProperties.getDefaultBackedText("jira.clone.linktype.name");
def jsBuilder=new JsonBuilder();
def issueLinkTypes = ((IssueLinkTypeManager) ComponentAccessor.getComponentOfType(IssueLinkTypeManager.class)).getIssueLinkTypes();
jsBuilder issueLinkTypes.findAll({it.getName().contains(HIDDEN_IDENT) || it.getName()==appClonersLinkTypeName }),
{ IssueLinkType linkType ->
issueLinkType linkType.getId(),
name: linkType.getName(),
inwardDescription: linkType.getInward(),
outwardDescription: linkType.getOutward()
}
return Response.ok(jsBuilder.toString()).build();
}
What you can do then ist just annotate and Link-Type with putting [hidden] in the link name and it will disappear for all users (It can still be programmatically added though or created by cloning).
If you don't have Scriptrunner or don't need the dynamic nature of the implementation, you can still hard-code the values as Kuf described in the answer above in hideIssueTypes() like this:
AJS.$("#issue-link-link-type option[value*='clon']").remove();