Can't select nothing inside draggable modal window - javascript

Please someone help. I'm really broken my brain on this. Neither select text inside modal nor click on input to type text into it.
I think it's because of z-index bugs. But can't find them.
var currentZ = null,
baseZ = 1000,
maxZ = 2000;
Here is an example: http://jsfiddle.net/emvc79sa/1/
This is directive angular-html-window

I'm not sure why the directive author set it this way, but your click actions are consumed by this line:
Window.prototype = {
_resizing: null,
_moving: null,
_restore: null,
events: {
wnd_mousedown: function(event) {
this.focus();
event.preventDefault(); // this line
},
Commenting out this line will let you highlight as normal but I'm not sure if there is any side effects.

Related

Monaco Editor: only show part of document

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.

Apply background-color in ckeditor textarea

I'm having some problems to apply a background-color in the textarea of a ckeditor instance.
When the user clicks on submit without adding any text, it's shown a message telling him to fill all the required fields, and these required fields areas all with the text-fields set with background-color: #CFC183;.
As the ckeditor is created with javascript code, I was using it to try to check if there's any text entered in the text area. if there's no character, I apply the changes.
When I apply in the console this code:
CKEDITOR.instances.body.document.getBody().setStyle('background-color', '#CFC183');
It applies the background exactly like I want to.
So, I added this javascript code in my javascript file to try to manage it, but doesn't seems to be working. Here's my code:
var editorInstance = CKEDITOR.replace('body', { toolbar : 'Full' });
editorInstance.on("instanceReady", function (ev) {
var editorCKE = CKEDITOR.instances.body; readyMap[editorCKE] = true;
editorCKE.setReadOnly(true);
});
var hasText = CKEDITOR.instances.body.document.getBody().getChild(0).getText();
if (!hasText) {
CKEDITOR.on('instanceCreated', function(e) {
e.editor.document.getBody().setStyle('background-color', '#CFC183');
});
}
Firebug shows this error message:
TypeError: CKEDITOR.instances.body.document is undefined
I'm not that good at Javascript, so is there anything wrong with my code?
I already checked this question here, so I believe there's something wrong with my javascript code and I want your help, please.
I guess that you've got an error in this line:
var hasText = CKEDITOR.instances.body.document.getBody().getChild(0).getText();
This is because you're trying to get document element before it's ready (before instanceReady event).
The same error will be thrown here:
if (!hasText) {
CKEDITOR.on('instanceCreated', function(e) {
e.editor.document.getBody().setStyle('background-color', '#CFC183');
});
}
Again - instanceCreated is still too early. You have to move all that code to instanceReady listener. You'll have something like (I'm not sure if I understand what you're trying to achieve):
var editor = CKEDITOR.replace( 'body', { toolbar: 'Full' } );
editor.on( 'instanceReady', function( evt ) {
readyMap[ editor.name ] = true;
editor.setReadOnly( true );
var hasText = editor.document.getBody().getFirst().getText();
if ( !hasText ) {
editor.document.getBody().setStyle( 'background-color', '#CFC183' );
}
} );
As you can see, there is one more issue in your code:
readyMap[editorCKE] = true;
In JS there are no weak maps (yet, but they will be introduced soon). Only strings can be used as a keys of an object. In your case toString() method will be called on editorCKE, which returns [object Object]. That's why I added name property there.

jquery and multiple element hover check

I have 3 boxes and once user hovers any, if changes the content of the big main div from default to the related div via featVals hash table
At the if ($('#estate-feature, #carrier-feature, #cleaning-feature').is(':hover')) { part of my code, I want to check if any of these 3 div boxes are currently hovered, if not display the default content (defaultFeat variable).
However I am getting Uncaught Syntax error, unrecognized expression: hover error from Google Chrome Javascript Console.
How can I fix it ?
Regards
$('#estate-feature, #carrier-feature, #cleaning-feature').hover(function () {
var currentFeatCont = featVals[$(this).attr('id')];
headlineContent.html(currentFeatCont);
}, function () {
headlineContent.delay(600)
.queue(function (n) {
if ($('#estate-feature, #carrier-feature, #cleaning-feature').not(':hover')) {
$(this).html(defaultFeat);
}
n();
})
});
:hover isn't an attribute of the element. Also, you are binding to the hover out there so you know that you have left the hover and can restore the default content. If you want the hover-triggered content to remain for a period after the point has left the trigger element then you'll either need to assume that you aren't going to roll over another trigger or implement a shared flag variable that indicates if the default text restore should be halted. e.g.
var isHovered = false;
$('#estate-feature, #carrier-feature, #cleaning-feature').hover(
function() {
var currentFeatCont = featVals[$(this).attr('id')];
headlineContent.html(currentFeatCont);
isHovered = true;
},
function() {
isHovered = false;
headlineContent.delay(600)
.queue(function(n) {
if (!isHovered) {
$(this).html(defaultFeat);
}
n();
})
}
);

javascript/jquery leaking and crashing browser

Let me just preface by saying it's actually my crappy code that's leaking and crashing my browser, I just thought I better make the languages being used as clear as I could from the outset.
I have a test page here and the javascript can be found here. My problem is that when I try and drag and drop either one of the red pieces more than a few times it sucks up all browser resources and crashes the browser. I'm fairly certain the culprit is something in the following function in the Tracker() object but I'm absolutely stuck on how to debug this.
My current most likely culprit:
function register_draggable(ob) {
ob.config.jqId.draggable({cursor: 'move',
grid:[ob.config.size, ob.config.size],
containment: '#chessboard',
revert: 'invalid',
start: function() {
check_allowable_moves(ob.config.jqLocation,
ob.config.jqId,
ob);
},
stop: function() {
remove_allowable_moves();
}
});
}
If anyone could take a quick look and give me any suggestions on what I should be looking for, it would be enormously appreciated.
Solution
Turns out register_draggable() was the culprit. I registered a new draggable every time the location of a piece updated and all those draggables on the same object were doing nasty things.
Currently I now explicity destroy the old draggable before creating a new one. Current code is
function register_draggable(ob) {
ob.config.jqId.draggable('destroy');
ob.config.jqId.draggable({cursor: 'move',
grid:[ob.config.size, ob.config.size],
containment: '#chessboard',
revert: 'invalid',
start: function() {
check_allowable_moves(ob.config.jqLocation,
ob.config.jqId,
ob);
},
stop: function() {
remove_allowable_moves();
}
});
}
I don't think this is actually your problem, but it seems like your making an extra method call on register and check_ allowable_moves
return {
register_map: function(ob) { map = ob; },
register_piece: function(ob) {
ob.config.tracker = this;
register_draggable(ob);
},
register_draggable: function(ob) { register_draggable(ob); },
check_allowable_moves: function(location, jqPiece, ob) { check_allowable_moves(location, jqPiece, ob); }
}
can be shortened to
return {
register_map: function(ob) { map = ob; },
register_piece: function(ob) {
ob.config.tracker = this;
register_draggable(ob);
},
register_draggable: register_draggable,
check_allowable_moves: check_allowable_moves
}
Also
you are doing a double lookup here:
function remove_allowable_moves() {
$('.allowable').droppable('destroy');
$('.allowable').removeClass('allowable');
}
should be
function remove_allowable_moves() {
$('.allowable').droppable('destroy')
.removeClass('allowable');
}
Also
Whats the purpose of parsing and int into a float? Take off the parseFloat.
var x = parseInt(locs[1]);
var y = parseInt(locs[2]);
var x_min = parseFloat(x)-2;
var y_min = parseFloat(y)-2;
Finally
Why are you re-registering as draggable on drop? This could be the culprit, if your registering the draggable multiple times and only destroying it once.
jqCell.droppable({ accept: '#'+jqPiece.attr('id'),
drop: function(ev, ui) {
ob.config.jqLocation = $(this);
register_draggable(ob); // why this?
}
});
Other thoughts
Another thing I don't know if its going to help your performance, but it could clean up your code. the jquery selector allows commas so instead of
$('#coord-1-1').doStuff();
$('#coord-1-2').doStuff();
$('#coord-1-3').doStuff();
you could do
$('#coord-1-1, #coord-1-2, #coord-1-3').doStuff();
so your loop would only be concerned with generating the selector string and then you could run you operation on the entire set.
IMO a cleaner init
instead of
var map = new Map('content');
var piece1 = new Piece(map);
var piece2 = new Piece(map);
var tracker = new Tracker;
tracker.register_map(map);
map.render();
piece1.render('coord-4-4', '1');
piece2.render('coord-1-1', '2');
tracker.register_piece(piece1);
tracker.register_piece(piece2);
I'd like to see
$(document).ready(function() {
$('#content').MapGame({
pieces : { '1' : 'coord-4-4', '2' : 'coord-1-1' }
});
});
Now implementing that is a strech from what you have now, but when building a component for jQuery I like to start with a simple init and work from their. Thats one of the big goals of jQuery is to hide all the junk from the user and just let them spin up and instance of your plugin easily.
It feels like some event-handlers are registered multiple times, but I'm unsure. (Reason below.)
That doesn't answer the question, but you absolutely should put as much code outside of $(document).ready(…) as possible, in no case put all your code in there as you do now.
I fear that your code is so ineligible that it's too much work to understand it. Could you restructure it (All those function-in-function are really horrible to read.) and add some comments.
Maybe it's just me, but I find it too hard to read and understand. It's surely going to be a disaster to maintain.

Comparison between Javascript objects

I have made a simple accordion for my site using jQuery... It worked great, but I've recently started working on a change where if you click the currently opened segments title (the clickable area to slide up/down), it should close the current section.
var sideMenu = {
activated: {},
setup: function() {
$('.menu-category-heading').bind('click', function() {
sideMenu.slideMenu($('ul', $(this).parent()));
});
},
slideMenu: function(menuObj) {
if (sideMenu.activated == menuObj) {
$(sideMenu.activated).slideUp(400);
sideMenu.activated = null;
console.log('same');
} else {
$(sideMenu.activated).slideUp(400);
menuObj.slideDown(500);
sideMenu.activated = menuObj;
console.log('new');
}
}
}
For some reason the comparison is never working... it does if I add $(menuObj).attr('id') and the same for activated. But this is not ideal as not all items will have an id attribute.
Any suggestions as to make the object comparison work? Or any other tips?
Thank you!
You are probably saving a jQuery object (the result of a $ call) rather than the native element. Each time you do a $(myEl) a new object is created and the references will not match up, but the native element will. Try:
if (slideMenu.activated[0] == menuObj[0]) {
...
}

Categories