Append keystrokes to div JS - javascript

I was wondering which, if any, framework would be the best to achieve capturing keystrokes and appending these to, say a "p" element. What I'm trying to achieve is having the client type something on the keyboard, and then have that sentence or whatever, appended to html, hereby displaying it in the "p" element.
Important notice; I'm not trying to call a function at a given keypress - ex. shift+alt, rather what I'm trying to do is, streaming the keyboardstrokes to an html element.

You don't necessarily need a framework for that task.
Another possbily viable option besides Kai Christensen's would be to create a textbox outside of the visible screen area, set the focus to this textbox automatically and create a change listener for the textbox.
You can then simply replace the content of the target element with the textbox's content whenever it changes.
This saves you the trouble of listening to keyboard events manually, distinguishing upper and lower case letters etc.

I would definitely go with jQuery to capture the keys and then constantly .replace() your div with a div with the same properties that contains the latest version of the updating string. Codecademy has a great set of lessons for this type of jQuery use.
Not that I'm an expert, though. I'm sure someone else has a better answer than my own.

Something like this?
Html
<p id="text"></p>
<input id="textinput"></input>
Js
//Register on keyup, append text from input-field to <p> element.
window.addEventListener("keyup", function () {
document.getElementById("text").innerHTML=document.getElementById('textinput').value;
});
jsfiddle: https://jsfiddle.net/vwobq9xf/1/

Related

Show context-menus only when certain elements are clicked

I am kinda stuck with something and I need your help.
I am trying to show context-menus only when a user right-clicks on a certain elements in the page.
I thought I solve this problem by using getElementByClassName(...) and adding an onClick listener to each one of the elements, and when the user clicks on any of them I will then create the context-menus. And then remove the content menu later when everything is done.
Problem is that I don't have the full class names of those elements, all I know that they start with "story".
I am not sure how to go about doing this. Is there a way to use regex and getting all elements with a class name of story? Or is that not possible.
Thanks in advance,
There's this library that allows for regex selectors.
<div class="story-blabla"></div>
$("div:regex(class, story.*)")
However, you may not want to implement a full library. There's another solution:
$('div').filter(function() {
return this.class.match(/story.*/);
})
This will return the objects you want.
You can do this using attribute starts with selector
document.querySelectorAll("[class^=story]")

HTML5,draggable and contentEditable not working together

When a draggable attribute is enabled on a parent element(<li>) I cant make contenteditable work on its child element (<a>).
The focus goes on to child element (<a>),but I cant edit it at all.
Please check this sample
http://jsfiddle.net/pavank/4rdpV/11/
EDIT: I can edit content when I disable draggable on <li>
I came across the same problem today, and found a solution [using jQuery]
$('body').delegate('[contenteditable=true]','focus',function(){
$(this).parents('[draggable=true]')
.attr('data-draggableDisabled',1)
.removeAttr('draggable');
$(this).blur(function(){
$(this).parents('[data-draggableDisabled="1"]')
.attr('draggable','true')
.removeAttr('data-draggableDisabled');
});
});
$('body') can be replaced by anything more specific.
If new contenteditable elements are not added in the runtime, one can use bind instead of delegate.
It makes sense that the draggable and contenteditable properties would collide. contenteditable elements, like any text field, will focus on mousedown (not click). draggable elements operate based on mousemove, but so does selecting text in a contenteditable element, so how would the browser determine whether you are trying to drag the element or select text? Since the properties can't coexist on the same element, it appears that you need a javascript solution.
Try adding these two attributes to your anchor tag:
onfocus="this.parentNode.draggable = false;"
onblur="this.parentNode.draggable = true;"
That works for me if I add it to the <a> tags in your jsFiddle. You could also use jQuery if it's more complicated than getting the parentNode.
Note: This is a workaround since I believe the inability for these two functionalities to work together resides in the HTML spec itself (i.e. the not working together thing is intentional since the browser can't determine whether you want to focus or drag on the mousedown event)
I noticed you explicitly set 'no libraries', so I will provide a raw javascript/HTML5 answer
http://jsfiddle.net/4rdpV/26/
This was my crack at it.
First of all, it might be better to include the data in one single localStorage item, rather than scatter it.
storage={
'1.text':'test 1',
'2.text':'test 2'
}
if(localStorage['test']){
storage=JSON.parse(localStorage['test'])
}
this creates that ability, using JSON to convert between object and string. Objects can indeed be nested
I also added (edit) links next to the items, when clicked, these links will transform the items into input elements, so you can edit the text. After hitting enter, it transforms it back and saves the data. At the same time, the list items remain draggable.
After saving, hit F12 in chrome, find the console, and look in the localStorage object, you will see all the data was saved in localStorage['test'] as an Object using JSON.stringify()
I tried my best to design this to be scaleable, and I think I succeeded well enough; you just need to replace the HTML with a container and use a javascript for loop to write out several items, using the iterator of your choice to fill the parameter for edit(). For example:
Say you changed storage to hold "paradigms" of lists, and you have one called "shopping list". And say the storage object looks something like this:
{
"shopping list":{
1:"Milk",
2:"Eggs",
3:"Bread"
}
}
This could render that list out:
for(i in storage['shopping list']){
_item = storage['shopping list'][i];
container.innerHTML+='<li draggable=true><a id="item'+i+'">'+_item+'</a> (edit)</li>'
}
Of course, if you were to edit the structure of the storage object, you would need to edit the functions as well.
The output would look something like this:
Milk (edit)
Eggs (edit)
Bread (edit)
Don't worry about the input elements if that worries you; CSS can easily fix it to look like it didn't just change.
If you don't want the (edit) links to be visible, for example, you can do this in CSS:
a[href="#"]{
display:none;
}
li[draggable="true"]:hover a[href="#"]{
display:inline;
}
Now the edit links will only appear when you hover the mouse over the list item, like this version:
http://jsfiddle.net/4rdpV/27/
I hope this answer helped.
Using html5sortable and newer JQuery events (delegate is deprecated, answer 3 years after initial question), bug still affects Chrome 37. Contenteditable spans and html5sortable seem to play nice in other browsers. I know this is only partially relevant, just keeping documentation on changes I've noticed.
$(document).on('focus', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable('destroy'); // removes sortable from the whole parent UL
});
$(document).on('blur', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable({ connectWith: '.sortable' }); // re-adds sortable to the parent UL
});

Is there a onselect event for non-form elements?

Say I want to hide a span when the user highlights a bit of text containing that span, with the intention of copying that text on to his clipboard.
For example:
<p>The dragon <span class="tooltip">a large, mythical beast</span> belched
fire at St. George.</p>
I have found that in Firefox Mac, span.tooltip will disappear from view (in accordance with my CSS declarations) but will show up in the clipboard when it's copied there. I figured (wrongly?) that if I said "onHighlight, hide tooltip," maybe this wouldn't happen.
Though it may be more complicated, why not just have an onmousedown event on the <p> element, and thet event will then attach an onmousemove event and onmouseout event, so that if there is a mouse movement, while the button is down, then remove the class on the span elements, and once the user exits, the element then you can put them back.
It may be a bit tricky, and you may want to also look for key presses, or determine other times you want to know when to put back the css classes, but this would be one option, I believe.
It sounds like you need to go one step further and on highlight, remove the <span> and save a reference to it. Once the highlight is finished, re-insert the reference to the object.
// copy start detected
var savedTooltip = $('.tooltip').remove();
// later that day when copy finished
$('p').append(savedTooltip);
If position of the <span> in your markup is important, you'd have to create a temporary reference element so you'd know where to re-insert it in the DOM.

Fire JavaScript event on object creation

Is there any way to fire an event when an object of a certain type is created?
I have an <div> element with editableContent="true" and when the user presses enter within the <div>, a new <div> is created that takes up just that line. Is it possible to have an event fire whenever a <div> object is created within my original <div> object?
I know one way to do this would to listen for keystrokes and on an 'enter' key being pressed, do a bunch of logic to figure out what to do, but this seems a lot less elegant - so it would be great if there was another way.
There are the a bunch of DOM Events and some of them will be supported by firefox for example. But I dont think that IE will support only one of them. Here is a complete list.
First you can fire a custom event every time you create a new div, or you have a settimeout that checks every second if the count of you divs childnodes has changed.
You have a function that creates a div when you press enter. Why don't you just add a function call at the end of it.
function createDiv(){
//create div
//append div
divCreated();
}
There's no default callbacks for new elements creating. The first thing I have in mind - you can add an event listener for mouseUp event and check content delta (changed part) - if it looks like an element markup with regexp.
Everybody who looking for a way to react to changes in a DOM should take into consideration MutationObserver. It is a standard DOM4 feature currently implemented in all latest (even not all modern but latest!) browsers.

How can I implement this interaction model with jQuery?

With jQuery, I'm interested in creating the following interaction model.
When a user types in the page, anytime jQuery notices three !, "!!!" typed in a row, to be able to do something about it.
After noticing three !, "!!!", wrap the previous sentence (finding the last period from the location the user is currently typing and wrapping a <span class=Important>
How can I do this?
This should work. I've set it up as a live event handler (so that it works for elements dynamically added to the page), but you could use the exact same function as a normal keyup handler on any textarea or input element as well.
It checks to see whether the element's current value ends with !!! and if so performs the replacement, both using simple regular expressions.
$("input,textarea").live("keyup", function() {
var $this = $(this);
var value = $this.val();
if (/!!!$/.test(value)) {
$this.val(value.replace(/(\.?)([^.]+?\.?\s*)!!!$/, '$1<span class="important">$2</span>'));
}
});
As much as I am loathe to say that jQuery isn't good for something - perhaps this kind of logic is better handled on the server. Unless they are typing in an HTML editor where the newly inserted span tags are invisible to the user, it may be a little disconcerting to be typing in a textarea/textbox and suddenly see a bunch of HTML inserted into my comment.

Categories