I have two spring boot services.
The frist one is an AuthServer (#EnableAuthorizationServer)
The secoind one is a ResourceServer (#EnableResourceServer)
When I call a method of the REST interface of the ResourceServer, without sending a valid token I get the following error in Postman:
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">
body {
font-family: Tahoma, Arial, sans-serif;
}
h1,
h2,
h3,
b {
color: white;
background-color: #525D76;
}
h1 {
font-size: 22px;
}
h2 {
font-size: 16px;
}
h3 {
font-size: 14px;
}
p {
font-size: 12px;
}
a {
color: black;
}
.line {
height: 1px;
background-color: #525D76;
border: none;
}
</style>
</head>
<body>
<h1>HTTP Status 500 – Internal Server Error</h1>
</body>
</html>
An Error-HTML-Page...but I would prefer something like this:
{
"timestamp": "2020-07-19T08:59:06.002+00:00",
"status": 401,
"error": "Invalid Token",
"message": "Plz use a valid token",
"path": "/rest/portfolio/2"
}
How can I set my custom auth-failure response? Do I have to do that in the AuthServer-Service or at the ResourceServer?
If I send no Authoriation-Header at all I get
<UnauthorizedException>
<error>unauthorized</error>
<error_description>Vollständige Authentifikation wird benötigt um auf diese Resource zuzugreifen</error_description>
</UnauthorizedException>
I would prefer to replace this with a custom message too.
Thank you very much
You need to have your own Authentication Entry Point and configure it in ResourceServerConfigurerAdapter -> (HttpSecurity http) like
...
.and()
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
...
Sample Auth Entry Point:
/**
* Returns a 401 error code (Unauthorized) to the client.
*/
#Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Autowired
com.fasterxml.jackson.databind.ObjectMapper mapper;
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ae) throws IOException, ServletException {
Map<String, Object> jsonResponse = new HashMap<>();
jsonReponse.put("status", false);
/*Put everything else into this map or better you can have a class to hold your response and initialise that here */
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
objectMapper.writeValue(response.getWriter(), responseJson);
}
}
Related
I have created a video call application using Nodejs & Twilio CLI. And using this in my both mobile app Android & iOS. On Android is working perfectly. But on iOS, there is an issue, when users reach the video call page, it's showing preview but as the user clicks on the Join Room button, then his/her video stops and just showing a black screen. While he can talk with other users and can see the video of them. And the Second user also can see his/her video perfectly. Only the issue he/she can't see his/her video on that call.
My html code
<!DOCTYPE html>
<html>
<head>
<style>
.joinbtn {
border: none;
padding: 10px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
margin: 4px 2px;
cursor: pointer;
background-color: #2b96cc;
color: #fff;
}
.stvbtn {
border: none;
padding: 10px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
margin: 4px 2px;
cursor: pointer;
background-color: #2b96cc;
color: #fff;
}
.endbtn {
float:right;
border: none;
padding: 10px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
margin: 4px 2px;
cursor: pointer;
background-color: #dc3545;
color: #fff;
}
#media screen and (max-width: 820px) {
video {
object-fit: cover;
width: 100%;
height: 47vh;
}
}
#media screen and (min-width: 821px){
video {
object-fit: contain;
}
}
.connect_btn{
display: flex;
justify-content: center;
align-content: space-around;
margin-top: -50px;
opacity: 0.8;
padding-bottom:8px;
}
button.endbtn:disabled, button.joinbtn:disabled {
background-color: #607d8b;
color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.4.0/adapter.js" type="text/javascript"></script>
<script src="webrtc.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Clifix Video Chat</title>
</head>
<body>
<div id="room-controls">
<video id="video" autoplay muted playsinline loop width="100%"></video>
<div class="connect_btn">
<label for="passcode"></label>
<input id="passcode" type="hidden" value="8514"/>
<!--button class="stvbtn" id="start-video" onclick="viplay()">On/Off</button-->
<button class="joinbtn" id="button-join">Join Room</button>
<button class="endbtn" id="button-leave" disabled="disabled">End Call</button>
</div>
</div>
<!-- EDIT_CODE -->
<script src="//media.twiliocdn.com/sdk/js/video/releases/2.3.0/twilio-video.min.js"></script>
<script src="index.js"></script>
</body>
</html>
My nodejs code:
'use strict';
(() => {
//const ROOM_NAME = 'demo';
var urltemp = location.search;
var array = urltemp.split('?');
var array1 = array[1];
var array2 = array1.split('=');
var id = array2[1];
const ROOM_NAME = id;
const Video = Twilio.Video;
let videoRoom, localStream;
const video = document.getElementById('video');
// preview screen
navigator.mediaDevices
.getUserMedia({ video: true, audio: true })
.then((vid) => {
video.srcObject = vid;
localStream = vid;
});
// buttons
const joinRoomButton = document.getElementById('button-join');
const leaveRoomButton = document.getElementById('button-leave');
joinRoomButton.onclick = () => {
//video.play();
// get access token
fetch(`video-token?passcode=${getPasscode()}&room=${ROOM_NAME}`)
.then((resp) => {
if (resp.ok) {
var url=window.location.href,
separator = (url.indexOf("?")===-1)?"?":"&",
newParam=separator + "join=true";
var newUrl=url.replace(newParam,"");
newUrl+=newParam;
window.history.replaceState(null,null,newUrl);
return resp.json();
} else {
console.error(resp);
if (resp.status === 401) {
throw new Error('Go Back & Join Again');
} else {
throw new Error('Unexpected error. Open dev tools for logs');
}
}
})
.then((body) => {
const token = body.token;
//console.log(token);
//connect to room
return Video.connect(token, { name: ROOM_NAME });
})
.then((room) => {
//console.log(`Connected to Room ${room.name}`);
videoRoom = room;
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', (error) =>
room.participants.forEach(participantDisconnected)
);
joinRoomButton.disabled = true;
leaveRoomButton.disabled = false;
})
.catch((err) => {
alert(err.message);
});
};
// leave room
leaveRoomButton.onclick = () => {
var url=window.location.href,
separator = (url.indexOf("?")===-1)?"?":"&",
newParam=separator + "end=true";
var newUrl=url.replace(newParam,"");
newUrl+=newParam;
window.history.replaceState(null,null,newUrl);
videoRoom.disconnect();
//console.log(`Disconnected from Room ${videoRoom.name}`);
joinRoomButton.disabled = false;
leaveRoomButton.disabled = true;
};
})();
const getPasscode = () => {
const passcodeInput = document.getElementById('passcode') || {};
const passcode = passcodeInput.value;
passcodeInput.value = '';
return passcode;
};
// connect participant
const participantConnected = (participant) => {
//console.log(`Participant ${participant.identity} connected'`);
const div = document.createElement('div'); //create div for new participant
div.id = participant.sid;
participant.on('trackSubscribed', (track) => trackSubscribed(div, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
participant.tracks.forEach((publication) => {
if (publication.isSubscribed) {
trackSubscribed(div, publication.track);
}
});
document.body.appendChild(div);
};
const participantDisconnected = (participant) => {
//console.log(`Participant ${participant.identity} disconnected.`);
document.getElementById(participant.sid).remove();
};
const trackSubscribed = (div, track) => {
div.appendChild(track.attach());
};
const trackUnsubscribed = (track) => {
track.detach().forEach((element) => element.remove());
};
As per my understanding, before this my video was not working on iOS safari then I have done modifications in my HTML video code.
From this:
<video id="video" autoplay muted width="100%"></video>
To:
<video id="video" autoplay muted playsinline loop width="100%"></video>
Then it starts working as having video freezing at the iOS User side when he/she start calling.
Twilio developer evangelist here.
When you call Video.connect the Video SDK will ask for permission to use your microphone and camera. Safari does not like giving access to the microphone and camera more than once at a time and since you also ask for media access to show the preview, it drops the preview tracks and creates new tracks for the video call. This is why the preview goes dark, but other participants can see and hear the video/audio.
Instead, you should reuse the tracks that you got for the preview by storing a reference to them and then passing them to Video.connect as the tracks property in the ConnectOptions. You already store a reference to the localStream so you can use that when you get to connect, like this:
return Video.connect(token, {
name: ROOM_NAME,
tracks: localStream.getTracks()
});
That way the tracks for the preview will be re-used for the video call and nothing should go dark.
I want to make a get request to url in rego. But it raises Invalid parameter: unallowed built-in function call in rego module: http.send error
Here is my code.
package play
default hello = false
hello {
response := http.send({
"method" : "GET",
"url": "http://localhost:8181/v1/data/example"
})
}
What I'm doing wrong?
That example is correct however https://play.openpolicyagent.org does not permit the http.send function for security reasons. Try it locally.
$ opa run
Inside the REPL:
> http.send({"method": "get", "url": "https://example.com"})
{
"body": null,
"raw_body": "\u003c!doctype html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n \u003ctitle\u003eExample Domain\u003c/title\u003e\n\n \u003cmeta charset=\"utf-8\" /\u003e\n \u003cmeta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" /\u003e\n \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /\u003e\n \u003cstyle type=\"text/css\"\u003e\n body {\n background-color: #f0f0f2;\n margin: 0;\n padding: 0;\n font-family: -apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n \n }\n div {\n width: 600px;\n margin: 5em auto;\n padding: 2em;\n background-color: #fdfdff;\n border-radius: 0.5em;\n box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);\n }\n a:link, a:visited {\n color: #38488f;\n text-decoration: none;\n }\n #media (max-width: 700px) {\n div {\n margin: 0 auto;\n width: auto;\n }\n }\n \u003c/style\u003e \n\u003c/head\u003e\n\n\u003cbody\u003e\n\u003cdiv\u003e\n \u003ch1\u003eExample Domain\u003c/h1\u003e\n \u003cp\u003eThis domain is for use in illustrative examples in documents. You may use this\n domain in literature without prior coordination or asking for permission.\u003c/p\u003e\n \u003cp\u003e\u003ca href=\"https://www.iana.org/domains/example\"\u003eMore information...\u003c/a\u003e\u003c/p\u003e\n\u003c/div\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n",
"status": "200 OK",
"status_code": 200
}
I am trying to set the custom CSS property of the PaperMenu node passed as content.
--paper-menu-background-color:green; works in the main document or when the PaperMenu is part of my custom component and are not in distributedNodes().
I have the following main.html
<html>
<head>
<meta charset="utf-8">
<link rel="import" href="packages/polymer_elements/paper_menu_button.html">
<link rel="import" href="packages/polymer_elements/paper_menu.html">
<link rel="import" href="packages/polymer_elements/paper_submenu.html">
<link rel="import" href="packages/polymer_elements/paper_item.html">
<link rel="import" href="packages/polymer_elements/paper_icon_button.html">
<link rel="import" href="packages/polymer_elements/paper_badge.html">
<link rel="import" href="packages/my_p/my_menu_bar.html">
</head>
<body unresolved>
<my-menu-bar>
<paper-menu>
<paper-submenu>
<paper-item class="menu-trigger">Topics</paper-item>
<paper-menu raised class="menu-content">
<paper-item>Topic 1</paper-item>
<paper-item>Topic 2</paper-item>
<paper-item>Topic 3</paper-item>
</paper-menu>
</paper-submenu>
</paper-menu>
</my-menu-bar>
<script type="application/dart" src="index.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
I don't want the below in the main.html though it works:
<style is="custom-style">
:root{--paper-menu-background-color:green;}
</style>
my_menu_bar.html
<dom-module id="my-menu-bar">
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
vertical-align: text-top;
--paper-menu-background-color:green;
<!--Does not work, setting colors via script-->
}
</style>
<template>
<div id='my_menu_bar_div'>
<content></content>
</div>
</template>
</dom-module>
css below take effect but not '--paper-menu-background-color:green;'
display:inline-block; top:0; vertical-align: text-top;
Setting background color via dart script and reflection works:
#HtmlImport('my_menu_bar.html')
library m_p.lib.my_menu_bar;
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'package:polymer_elements/paper_input.dart';
import 'package:polymer_elements/paper_menu.dart';
import 'package:polymer_elements/paper_submenu.dart';
import 'package:polymer_elements/paper_item.dart';
import 'dart:async';
import 'package:web_components/web_components.dart';
import 'dart:mirrors';
#PolymerRegister('my-menu-bar')
class MyMenuBar extends PolymerElement {
MyMenuBar.created() : super.created() { }
void _recursive_set_style(var e, String attrName, String value){
// print(reflect(e).type.superclass.toString());
if(!(reflect(e).type.isSubtypeOf(reflectClass(HtmlElement))))
return;
// print('ya, it\'s subtype of HtmlElement');
InstanceMirror helperMirror = reflect(e.style);
var methodsAr = helperMirror.type.instanceMembers;
var sym = new Symbol(attrName);
print(methodsAr[sym]);
if(null !=methodsAr[sym]){
helperMirror.setField(sym,value);
}
for(var ie in e.children){
_recursive_set_style(ie,attrName,value);
}
}
attached() {
super.attached();
new Future(() {
ContentElement ce = Polymer.dom(this.root)
.querySelector('content');
PolymerDom dom = Polymer.dom(ce);
List<Node> nodes = dom.getDistributedNodes();
nodes.removeWhere((n)=>!(n is PaperMenu));
//Setting colors
updateStyles();
for(var e in nodes){
_recursive_set_style(e,'backgroundColor','rgb(156, 58, 53)');
}
});
}
}
Personally I like scripting over css, but love to know the standard way to do this and why this is happening.
Edit
Thanks to Günter Zöchbauer's comment, the function is now reduced to:
void _recursive_set_style(var e, String attrName, String value){
e.attributes[attrName]=value;
for(var ie in e.children){
_recursive_set_style(ie,attrName,value);
}
}
As to wrapping the content tag, it did not work or I'm doing something silly still.
Edit2
Hi, Günter Zöchbauer.
If you can help me confirm this, that would be great.
It's so hard to be sure about anything.
my-menu-bar:
<dom-module id="my-menu-bar">
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host ::content .special{
<!--setting class name did nothing-->
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host div#my_menu_bar ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div > ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
#my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
::content paper-menu{
--paper-menu-background-color:green;
}
paper-menu{
--paper-menu-background-color:green;
}
:root ::content paper-menu{
--paper-menu-background-color:green;
}
:root #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
:host ::content .paper-menu{
--paper-menu-background-color:green;
}
:host ::content #paper-menu{
--paper-menu-background-color:green;
}
</style>
<template>
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host ::content .special{
<!--setting class name did nothing-->
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host div#my_menu_bar ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div > ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
#my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
::content paper-menu{
--paper-menu-background-color:green;
}
paper-menu{
--paper-menu-background-color:green;
}
:root ::content paper-menu{
--paper-menu-background-color:green;
}
:root #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
:host ::content .paper-menu{
--paper-menu-background-color:green;
}
:host ::content #paper-menu{
--paper-menu-background-color:green;
}
</style>
<div id='my_menu_bar_div'>
<content></content>
</div>
</template>
</dom-module>
I tried debugger and it seems CSS variable sham and related values are taking effect before initPolymer() and standard CSS directives like "display:inline-block;".
Edit3
Hi, Günter Zöchbauer.
In response to your "This doesn't look right.", I double checked.
But I think css variable sham is the thing to blame. I mean, as I said first, the standard CSS directives are working on the distributed content.
Under shady DOM, the <content> tag doesn’t appear in the DOM tree.
Styles are rewritten to remove the ::content pseudo-element, and any
combinator immediately to the left of ::content.
The description is a little lacking, but from examples I assume it's telling me to have selectors to the right and the left of the ::content pseudo element and I think I always had that right.
Digging deeper requires javascript knowledge and I don't have that, I know javascript is the foundation of web but I'm no web programmer and want to cover wide before diving deep, so I will give up on this.
<dom-module id="my-menu-bar">
<template>
<style>
:host .content-wrapper > ::content div{
/* These CSS variables do not work*/
--paper-menu-background-color:blue;
--paper-item{
background-color:red;
}
/*The below works alright*/
/*background-color:green;*/
/*color:red;*/
}
:host .content-wrapper > ::content .special{
/* This and the above should have
the same scope of selection, but this one
does not work at all.
Encapsulation playing a trick idk.*/
/*background-color:green;*/
/*color:red;*/
}
:host ::content div{
/*works*/
/*background-color:green;*/
}
:host ::content {
/* does not work*/
/*background-color:green;*/
}
:host ::content paper-menu{
/*works but custom property and color*/
/*color:blue;*/
display:inline-block;
top:0;
vertical-align: text-top;
}
:host ::content paper-item{
/*works*/
/*color:blue;*/
}
</style>
<div class='content-wrapper'>
<content></content>
</div>
</template>
</dom-module>
Edit4
After a long and futile search, I believe I found it.
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/?redirect_from_locale=pt
What's conceptually bizarre about insertion points is that they don't
physically move DOM. The host's nodes stay intact. Insertion points
merely re-project nodes from the host into the shadow tree. It's a
presentation/rendering thing: "Move these nodes over here" "Render
these nodes at this location."
You cannot traverse the DOM into a <content>.
If I could set the value of a CSS variable for an outer light dom from within a shadow dom, that would break the encapsulation. While Color etc belongs to content pseudo element, css variables and mixins are macro that insert values into css place holders.
To make this work in shady DOM (default) you need to wrap the <content> tag in another tag and include this wrapper in the selector.
See https://www.polymer-project.org/1.0/docs/devguide/styling.html#styling-distributed-children-content (first example for more details)
If this still doesn't work it might be a limitation of the CSS variables shim.
<dom-module id="my-element">
<template>
<style>
/* styling elements distributed to content (via ::content) requires */
/* selecting the parent of the <content> element for compatibility with */
/* shady DOM . This can be :host or a wrapper element. */
.content-wrapper > ::content .special {
background: orange;
}
</style>
<div class="content-wrapper"><content></content></div>
</template>
</dom-module>
I am trying to find a working example of a Socket.io implementation on iOS with Swift, but have been unlucky so far. I did get a few examples from Github, but each have some issues and I cannot tell why they don’t work.
Does anyone know where I can get an out of the box working example, so that I can go through the code and understand the implementation?
Based on socket.io's examples:
Server (index.js, see socket.io website for setup):
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(8080, function(){
console.log('listening on *:8080');
});
Client (ViewController.swift):
import UIKit
import Socket_IO_Client_Swift
class ViewController: UIViewController {
#IBOutlet weak var chatView:UITextView!
#IBOutlet weak var sendButton:UIButton!
#IBOutlet weak var sendField:UITextField!
let socket = SocketIOClient(socketURL: "10.0.0.1:8080", opts: ["log": true])
override func viewDidLoad() {
super.viewDidLoad()
addHandlers()
self.socket.connect()
}
#IBAction func send() {
self.socket.emit("chat message", withItems: [self.sendField.text!])
self.sendField.text = ""
}
func addHandlers() {
self.socket.on("connect") {data, ack in
print("socket connected")
}
self.socket.on("chat message") {[weak self] data, ack in
if let value = data.first as? String {
self?.chatView.text?.appendContentsOf(value + "\n")
}
}
}
}
Web client (index.html, useful for testing):
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
</body>
</html>
Since I asked the question there have been changes and we now have socket.io for iOS. Here's the original blog post on it: http://socket.io/blog/socket-io-on-ios/
i want to create tags for input data.(http://textextjs.com/manual/examples/ajax-with-filter-tags-and-autocomplete.html hear they creating tags using auto complete text box, but i don't want auto complete one)
hear is my code
<!DOCTYPE html>
<html>
<head>
<script src="jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#textBox").keyup(function() {
$("#message").val($(this).val());
});
});
</script>
</head>
<body>
<div>
TextBox 1 : <input type="textbox" id="textBox"></input>
TextBox 2 : <input type="textarea" id="message"></input>
</div>
</body>
</html>
hear it reflect data of textbox1 to textbox2.
now what i want is : if user enter any data(words) in textbox1 followed by space then that word should convert into tags in textbox2
First of all type=textarea is wrong. There's no such input like that. You must be using <textarea> instead of that. Secondly, why dont you use contentditable attribute? It works just like a text area but can take HTML, is supported in all browsers, and you can use it on any block element! So replace your second input with this:
TextBox 2 : <div class="target" contenteditable="true"></div>
Then, in your code,
$("#textBox").keypress(function (e) {
if (e.which === 32) {
$(".target").append("<a href='#' class='tag'>" + this.value + "</a>");
this.value = "";
}
});
(Disclaimer) I used the styles from SO's tags, like this :
body {
font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif;
}
.tag {
color: #3E6D8E;
background-color: #E0EAF1;
border-bottom: 1px solid #b3cee1;
border-right: 1px solid #b3cee1;
padding: 3px 4px 3px 4px;
margin: 2px 2px 2px 0;
text-decoration: none;
font-size: 90%;
line-height: 2.4;
white-space: nowrap;
}
.tag:hover {
background-color: #c4dae9;
border-bottom: 1px solid #c4dae9;
border-right: 1px solid #c4dae9;
text-decoration: none;
}
Demo : http://jsfiddle.net/hungerpain/Wky2Z/
To add the tags to an array, have a variable called tags outside the keypress function :
var tags = [];
Then, in the keypress, you've got this if loop right? Push the new value into the array :
if (e.which === 32) {
$(".target").append("<a href='#' class='tag'>" + this.value + "</a>");
tags.push(this.value); //push the value in array
this.value = "";
}
Then, when you need to save it to DB, just join them :
tags.join("");
Then later, when you to retrieve them from DB next time, you could wrap those with the a (what we did in the keypress function)
Demo : http://jsfiddle.net/hungerpain/Wky2Z/1/
Try This:
$(document).ready(function () {
$("#textBox").keyup(function (e) {
if (e.keyCode == 32) {
$("#message").val($(this).val());
}
if ($(this).val() == '') {
$("#message").val('');
}
});
});
JSFIDDLE DEMO