How to set youtube theme parameter in JS? - javascript

I've been working on embedding a youtube playlist with Javascript and I can't change the theme to light. All the other parameters work but this one doesn't come through.
This is how think it should work:
var defoptions = {
autoplay: false,
user: null,
playlist: null,
carousel: createCarousel,
player: createPlayer,
thumbnail: createThumbnail,
max_results: 25, // does not apply to playlists
loaded: function () {},
playopts: {
autoplay: 0,
egm: 1,
autohide: 1,
fs: 1,
showinfo: 0,
rel: 0,
theme: light
}
};
Any thoughts?
Thanks!
Here you have the whole thing, it's far from finished but first I need to find out how to change the theme.
<style>
#container{
background-color: #F1F1F1;
padding: 20px;
}
.yt-descript{
max-width: 100px;
font-family: verdana;
font-weight: bold;
font-size: 9pt;
margin: 2px;
}
.player {
width: 100%;
height: 305px;
overflow: hidden;
background-color: #F1F1F1 ;
position: relative;
}
.youtube .carousel {
width: 20%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
position: absolute;
right: 0px;
z-index: 3;
}
.youtube .thumbnail {
margin-left: 2px;
width: 90%;
border: 1px solid black;
}
.youtube iframe.player {
width: 80%;
height: 100%;
overflow: auto;
border: 0;
}
</style>
<script>
(function () {
function createPlayer(jqe, video, options) {
var ifr = $('iframe', jqe);
if (ifr.length === 0) {
ifr = $('<iframe scrolling="no">');
ifr.addClass('player');
}
var src = 'http://www.youtube.com/embed/' + video.id;
if (options.playopts) {
src += '?';
for (var k in options.playopts) {
src += k + '=' + options.playopts[k] + '&';
}
src += '_a=b';
}
ifr.attr('src', src);
jqe.append(ifr);
}
function createCarousel(jqe, videos, options) {
var car = $('div.carousel', jqe);
if (car.length === 0) {
car = $('<div>');
car.addClass('carousel');
jqe.append(car);
}
$.each(videos, function (i, video) {
options.thumbnail(car, video, options);
});
}
function createThumbnail(jqe, video, options) {
var imgurl = video.thumbnails[0].url;
var img = $('img[src="' + imgurl + '"]');
var desc;
var container;
if (img.length !== 0) return;
img = $('<img align="left">');
img.addClass('thumbnail');
jqe.append(img);
img.attr('src', imgurl);
img.attr('title', video.title);
img.click(function () {
options.player(options.maindiv, video, $.extend(true, {}, options, {
playopts: {
autoplay: 1
}
}));
});
desk = $('<p class="yt-descript">' + video.title + '</p>');
jqe.append(desk);
desk.click(function () {
options.player(options.maindiv, video, $.extend(true, {}, options, {
playopts: {
autoplay: 1
}
}));
});
}
var defoptions = {
autoplay: false,
user: null,
playlist: null,
carousel: createCarousel,
player: createPlayer,
thumbnail: createThumbnail,
max_results: 25, // does not apply to playlists
loaded: function () {},
playopts: {
autoplay: 0,
egm: 1,
autohide: 1,
fs: 1,
showinfo: 0,
rel: 0
}
};
$.fn.extend({
youTubeChannel: function (options) {
var md = $(this);
md.addClass('youtube');
md.addClass('youtube-channel');
var allopts = $.extend(true, {}, defoptions, options);
allopts.maindiv = md;
var JSONurl = "";
if (allopts.playlist) {
JSONurl = 'http://gdata.youtube.com/feeds/api/playlists/' + allopts.playlist + '?alt=json-in-script&format=5&callback=?';
} else if (allopts.user) {
JSONurl = 'http://gdata.youtube.com/feeds/users/' + allopts.user + '/uploads?alt=json-in-script&max-results=' + allopts.max_results.toString() + '&format=5&callback=?';
} else {
console.log('user or playlist must be specified');
}
$.getJSON(JSONurl, null, function (data) {
var feed = data.feed;
var videos = [];
$.each(feed.entry, function (i, entry) {
var video = {
title: entry.title.$t,
id: entry.link[3].href.match('[^/]*$'),
thumbnails: entry.media$group.media$thumbnail
};
videos.push(video);
});
allopts.allvideos = videos;
allopts.carousel(md, videos, allopts);
allopts.player(md, videos[0], allopts);
allopts.loaded(videos, allopts);
});
}
});
})();
// Playlist
$(function () {
$('#player1').youTubeChannel({
playlist: 'PLFE3E2A9A3BDD70BE'
});
});
// Channel
$(function () {
$('#player3').youTubeChannel({
user: 'YTusername',
max_results: 50
});
});
</script>
<div id="container">
<h1>Latest Videos</h1>
<div id="player1" class="player"></div>
</div>

Theme needs to value string values, so try this:
var defoptions = {
autoplay: false,
user: null,
playlist: null,
carousel: createCarousel,
player: createPlayer,
thumbnail: createThumbnail,
max_results: 25, // does not apply to playlists
loaded: function () {},
playopts: {
autoplay: 0,
egm: 1,
autohide: 1,
fs: 1,
showinfo: 0,
rel: 0,
theme: "light",
color: "white"
}
};

Related

QuaggaJs: Browser compatibility issue for barcode scanner

I am using QuaggaJs to scan the barcode. Everything is good and smooth for desktop version of scanner. But it gets broken when coming to mobile version of website and that too mainly on iPhone.
I tested in both safari and Chrome and for different phone it behaves differently. For some phone camera gets hang and for some camera didn't start at all.
Also, the canvas size is not setting up in the parent div. camera is getting outside the DOM.
Here is what I did.
HTML
<div class="scanner-box">
<div id="scanner-container" class="main_scanner"></div>
</div>
JS
$(document).ready(function(){
if($(".scanner-box").length > 0){
var canvas_width = $(".scanner-box").width();
var canvas_height = $(".scanner-box").height();
if (_scannerIsRunning) {
Quagga.stop();
} else {
startScanner(canvas_width,canvas_height);
}
}
}
var _scannerIsRunning = false;
function startScanner(canvasRatio,canvasHeight) {
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#scanner-container'),
constraints: {
width: "100%",
height: "100%",
facingMode: "environment"
},
},
decoder: {
readers: [
"ean_reader",
"ean_8_reader"
],
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
},
},
function (err) {
if (err) {
$("#error").text(err);
return
}
console.log("Initialization finished. Ready to start");
Quagga.start();
_scannerIsRunning = true;
});
Quagga.onProcessed(function (result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
}
}
});
Quagga.onDetected(function (result) {
var barcodeResult = $("#result").text(result.codeResult.code);
var barcode = result.codeResult.code;
if(barcode.toString().length < '13'){
}else{
checkBarCode(barcode,canvasRatio,canvasHeight);
if (_scannerIsRunning) {
Quagga.stop();
}
}
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
});
}
CSS
.scanner-box{width:480px;height:320px;background-color:#9a9a9a;position:relative;margin-top:10px;}
#scanner-container{position:relative;height:inherit;}
#scanner-container canvas{
position: absolute;
left : 0px;
top: 0px;
}
this css is just like the sample form https://serratus.github.io/quaggaJS/v1.0.0-beta.1/examples/file_input/
it makes the canvas area which draws windows cover the camera steam area .

Link Page AFTER Toggle

I have a toggle button that animates. After it has animated I want the user to be redirected to a different page. This code comes from: https://codemyui.com/flipping-egg-toggle-switch/
I haven't used toggles before and wasn't sure if there was a standard way to do this.
Thanks!
Code:
var select = function(s) {
return document.querySelector(s);
},
selectAll = function(s) {
return document.querySelectorAll(s);
},
animationWindow = select('#animationWindow'),
animData = {
wrapper: animationWindow,
animType: 'svg',
loop: false,
prerender: false,
autoplay: false,
path: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/35984/egg_flip.json'
},
anim;
anim = bodymovin.loadAnimation(animData);
anim.addEventListener('DOMLoaded', onDOMLoaded);
anim.setSpeed(15);
function onDOMLoaded(e) {
animationWindow.onclick = function(e) {
if (anim.currentFrame > 0) {
anim.playSegments([anim.currentFrame, 0], true);
TweenMax.to('.eggGroup', 1, {
x: 0,
ease: Elastic.easeOut.config(0.9, 0.38)
})
} else {
TweenMax.to('.eggGroup', 1.4, {
x: 73,
ease: Elastic.easeOut.config(0.9, 0.38)
})
anim.playSegments([anim.currentFrame, 300], true)
}
}
}
body {
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#animationWindow {
width: 50%;
;
height: 50%;
-webkit-tap-highlight-color: transparent;
cursor: pointer;
<div id="animationWindow">
</div>
From TweenMax documentation: pass function as callback using onComplete property. For example:
TweenMax.to('.eggGroup', 1.4, {
x: 73,
ease: Elastic.easeOut.config(0.9, 0.38),
onComplete: function(){ ** do something ** };
})

Letter js delay

I'm using a plugin called Letter js to animate a four paragraphs using html jQuery and CSS.
The plugin works great but I have an issue trying to delay the animation of each paragraph i.e. paragraph 1 should start after 1 second, paragraph 2 should start after 2 seconds with other words making each paragraph appear gradually.
I tried adding the delay function after content but that didn't work, can anybody help?
// The plugin js (l-by-l.min.js) file is the following:
! function(e) {
e.fn.lbyl = function(n) {
{
var t = e.extend({
content: "",
speed: 10,
type: "fade",
fadeSpeed: 500,
finished: function() {}
}, n),
d = e(this),
s = [],
i = t.content;
e(this).length
}
d.empty(), d.attr("data-time", i.length * t.speed);
for (var p = 0; p < i.length; p++) s.push(i[p]);
e.each(s, function(e, n) {
d.append('<span style="display: none;">' + n + "</span>"), setTimeout(function() {
"show" == t.type ? d.find("span:eq(" + e + ")").show() : "fade" == t.type && d.find("span:eq(" + e + ")").fadeIn(t.fadeSpeed)
}, e * t.speed)
}), setTimeout(function() {
t.finished()
}, i.length * t.speed)
}
}(jQuery);
// My Script is the following:
jQuery(document).ready(function($) {
$(".welcome_Text1_dk").lbyl({
content: "this is paragraph one",
speed: 100, //time between each new letter being added
type: 'fade', // 'show' or 'fade'
fadeSpeed: 500, // Only relevant when the 'type' is set to 'fade'
finished: function() {
console.log('finished')
} // Finished Callback
})
});
jQuery(document).ready(function($) {
$(".welcome_Text2_dk").lbyl({
content: "this is paragraph two",
speed: 100, //time between each new letter being added
type: 'fade', // 'show' or 'fade'
fadeSpeed: 500, // Only relevant when the 'type' is set to 'fade'
finished: function() {
console.log('finished')
} // Finished Callback
})
});
jQuery(document).ready(function($) {
$(".welcome_Text3_dk").lbyl({
content: "this is paragraph three",
speed: 100, //time between each new letter being added
type: 'fade', // 'show' or 'fade'
fadeSpeed: 500, // Only relevant when the 'type' is set to 'fade'
finished: function() {
console.log('finished')
} // Finished Callback
})
});
jQuery(document).ready(function($) {
$(".welcome_Text4_dk").lbyl({
content: "this is paragraph four",
speed: 100, //time between each new letter being added
type: 'fade', // 'show' or 'fade'
fadeSpeed: 500, // Only relevant when the 'type' is set to 'fade'
finished: function() {
console.log('finished')
} // Finished Callback
})
});
#home_dk {
width: 100%;
height: 100vh;
background: #fff;
background-attachment: fixed;
display: flex;
flex-direction: column;
justify-content: center;
}
#welcome_Text_Wrapper_dk {
display: block;
margin-left: auto;
margin-right: auto;
width: auto;
}
.welcome_Text1_dk,
.welcome_Text2_dk,
.welcome_Text3_dk {
color: #b6b69c;
font-size: 2.6em;
font-family: "SuperGroteskWebPro-Bold W01 Rg";
text-transform: uppercase;
text-align: left;
line-height: 1em;
}
.welcome_Text4_dk {
color: #b6b69c;
font-size: 2.6em;
font-family: 'FF_Super_Grotesk';
text-transform: uppercase;
text-align: left;
line-height: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="home_dk">
<article id="welcome_Text_Wrapper_dk">
<div class="welcome_Text1_dk"></div>
<div class="welcome_Text2_dk"></div>
<div class="welcome_Text3_dk"></div>
<div class="welcome_Text4_dk"></div>
</article>
</div>
// The plugin js (l-by-l.min.js) file is the following:
! function(e) {
e.fn.lbyl = function(n) {
{
var t = e.extend({
content: "",
speed: 10,
type: "fade",
fadeSpeed: 500,
finished: function() {}
}, n),
d = e(this),
s = [],
i = t.content;
e(this).length
}
d.empty(), d.attr("data-time", i.length * t.speed);
for (var p = 0; p < i.length; p++) s.push(i[p]);
e.each(s, function(e, n) {
d.append('<span style="display: none;">' + n + "</span>"), setTimeout(function() {
"show" == t.type ? d.find("span:eq(" + e + ")").show() : "fade" == t.type && d.find("span:eq(" + e + ")").fadeIn(t.fadeSpeed)
}, e * t.speed)
}), setTimeout(function() {
t.finished()
}, i.length * t.speed)
}
}(jQuery);
// My Script is the following:
jQuery(document).ready(function($) {
// create an array of paragraphs
var myParagraphs = [{
selector: ".welcome_Text1_dk",
content: "this is paragraph one"
}, {
selector: ".welcome_Text2_dk",
content: "this is paragraph two"
}, {
selector: ".welcome_Text3_dk",
content: "this is paragraph three"
}, {
selector: ".welcome_Text4_dk",
content: "this is paragraph four"
}];
// loops it
for (let i = 0; i < myParagraphs.length; i++) {
setTimeout(function() {
$(myParagraphs[i].selector).lbyl({
content: myParagraphs[i].content,
speed: 100, //time between each new letter being added
type: 'fade', // 'show' or 'fade'
fadeSpeed: 500, // Only relevant when the 'type' is set to 'fade'
finished: function() {
console.log('finished')
} // Finished Callback
});
}, 1000 * i);
}
});
#home_dk {
width: 100%;
height: 100vh;
background: #fff;
background-attachment: fixed;
display: flex;
flex-direction: column;
justify-content: center;
}
#welcome_Text_Wrapper_dk {
display: block;
margin-left: auto;
margin-right: auto;
width: auto;
}
.welcome_Text1_dk,
.welcome_Text2_dk,
.welcome_Text3_dk {
color: #b6b69c;
font-size: 2.6em;
font-family: "SuperGroteskWebPro-Bold W01 Rg";
text-transform: uppercase;
text-align: left;
line-height: 1em;
}
.welcome_Text4_dk {
color: #b6b69c;
font-size: 2.6em;
font-family: 'FF_Super_Grotesk';
text-transform: uppercase;
text-align: left;
line-height: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="home_dk">
<article id="welcome_Text_Wrapper_dk">
<div class="welcome_Text1_dk"></div>
<div class="welcome_Text2_dk"></div>
<div class="welcome_Text3_dk"></div>
<div class="welcome_Text4_dk"></div>
</article>
</div>
You can use the setTimeout() function.
jQuery(document).ready(function($) {
// run first one here
setTimeout(function(){
// do the second one here
}, 1000); // in milliseconds; 1 second
setTimeout(function(){
// do the third one
}, 2000); // in milliseconds; 2 second
setTimeout(function(){
// do the fourth one here
}, 3000); // in milliseconds; 3 second
// etc.
});

Calling a DIV twice using Javascript

I'm using Subscribe2 and it works great. The form is called using the <div id="element"></div>
However, it shows once per page. I want to show it twice on the same page. One at the top of the page and another at the bottom. How should I go about it?
$(document).ready(function () {
$("#element").subscribe2({
options: {
method: "google",
formkey: "2eiFxDZOpcyjPo9ub7nIwp6vAKUkLIiOxXIPT1TtAAAA",
datakey: "entry.57553044"
},
});
});
This can help you.
Since there are no CDN repository for subscribe2, I have added the files in the custom script/css only.
(function($, window, document, undefined) {
"use strict";
var pluginName = "subscribe2",
defaults = {
buttonText: "Request Invite",
btnClass: "",
inputClass: "",
errorMessages: {
client: "Please enter a valid email address.",
server: "Error contacting server"
},
successMessage: "Thanks. We have added you to our list and you will be notified soon."
};
// Plugin constructor
function Plugin(element, options) {
if (!options.hasOwnProperty("options") || typeof options.options !== "object" || !options.options.hasOwnProperty("formkey") || !options.options.hasOwnProperty("datakey") || typeof options.options.formkey !== "string" || typeof options.options.datakey !== "string") {
console.error("Invalid Options. Refer https://github.com/abhas9/subscribe2");
return;
}
this.element = element;
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function() {
this.appendSubscribeBox();
},
postForm: function(inputValue) {
var data = {}, that = this;
data[this.settings.options.datakey] = inputValue;
var successCallback = function() {
that.inputView.css({
display: "none"
});
that.successMessage.css({
display: "block"
}).html(that.settings.successMessage);
}
$.ajax({
url: "https://docs.google.com/forms/d/" + this.settings.options.formkey + "/formResponse",
type: "POST",
dataType: "xml",
statusCode: {
0: successCallback,
200: successCallback
},
data: data
})
},
submitHandler: function() {
var inputValue = $(this.element).find(".subscribe2-control-input").val();
if (this.validateEmail(inputValue)) {
this.errorMessage.css({
display: "none"
});
this.postForm(inputValue);
} else {
this.errorMessage.html(this.settings.errorMessages.client).css({
display: "block"
});
}
},
inputKeyUp: function(event) {
var inputValue = $(this.element).find(".subscribe2-control-input").val();
if (event.which === 13) {
this.submitHandler();
} else {
this.errorMessage.css({
display: "none"
});
if (this.validateEmail(inputValue)) {
this.validationStatusIcon.css({
display: "block"
}).addClass("subscribe2-valid").removeClass("subscribe2-invalid").html("✓");
} else {
this.validationStatusIcon.css({
display: "block"
}).addClass("subscribe2-invalid").removeClass("subscribe2-valid").html("x");
}
}
},
validateEmail: function(value) {
var re = /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(value);
},
appendSubscribeBox: function() {
var subscribeInputWrp = $("<div>", {
class: "subscribe2-input-wrp"
});
var subscribeInput = $("<input>", {
type: "email",
class: "subscribe2-control-input " + this.settings.inputClass,
placeholder: "Email",
keyup: this.inputKeyUp.bind(this)
});
this.validationStatusIcon = $("<div>", {
class: "subscribe2-validation-status",
css: {
display: "none"
}
});
subscribeInputWrp.append(subscribeInput, this.validationStatusIcon);
var subscribeButton = $("<button>", {
text: this.settings.buttonText,
class: "subscribe2-btn " + this.settings.btnClass,
click: this.submitHandler.bind(this)
});
this.errorMessage = $("<div>", {
class: "subscribe2-error",
css: {
display: "none"
}
});
this.successMessage = $("<div>", {
class: "subscribe2-success",
css: {
display: "none"
}
});
var clearDiv = $("<div>", {
css: {clear: "both"}
});
this.inputView = $("<div>", {
class: "subscribe2-input-view",
append: [this.errorMessage, subscribeInputWrp, subscribeButton, clearDiv]
})
var subscribeBox = $("<div>", {
class: "subscribe2-wrp"
});
$(this.element).append(subscribeBox.append(this.inputView, this.successMessage));
}
});
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new Plugin(this, options));
}
});
};
})(jQuery, window, document);
$(document).ready(function () {
$(".element").subscribe2({
options: {
method: "google",
formkey: "2eiFxDZOpcyjPo9ub7nIwp6vAKUkLIiOxXIPT1TtAAAA",
datakey: "entry.57553044"
},
});
});
.subscribe2-wrp {
width: 100%;
max-width: 450px;
border: 1px solid #ccc;
}
.subscribe2-input-view {
padding: 10px 30px;
}
.subscribe2-input-wrp {
width: 70%;
float: left;
margin-right: 5%;
position: relative;
}
.subscribe2-btn {
width: 25%;
float: left;
}
.subscribe2-control-input {
width: 100%;
}
.subscribe2-validation-status {
display: block;
position: absolute;
right: 0;
top: 2px;
border-radius: 50%;
width: 10px;
height: 10px;
text-align: center;
padding: 2px;
font-size: 12px;
line-height: 12px;
vertical-align: middle;
color: #fff;
}
.subscribe2-valid {
background: #49BF49;
border: 1px solid #6DBD6D;
}
.subscribe2-invalid {
background: #c0392b;
border: 1px solid #B13326;
line-height: 9px;
font-family: 'Century Gothic', CenturyGothic, AppleGothic, sans-serif;
}
.subscribe2-success {
padding: 10%;
}
#media only screen and (max-width: 480px) {
.subscribe2-input-wrp {
width: 100%;
}
.subscribe2-btn {
width: 90%;
margin: 10px auto;
}
}
#footer {
position: fixed;
bottom: 0;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="subscribe2/src/jquery.subscribe2.css">
<div class="element"></div>
<div class="element" id="footer"></div>

Add port to a custom elements in jointJS

I am new to jointJs library and I am trying to add ports to my custom element that contains html code in it. I followed this tutorial (http://www.jointjs.com/tutorial/html-elements) and created my element. But when I try to add ports to it (based on this tutorial: http://www.jointjs.com/tutorial/ports) it does not work.
Another problem I have is that I want the textbox(textarea on my custom shape) to disappear when I click on the blank paper, and just the label with its content stays visible on the element. For that I used the following piece of code (but it does not give me the above-mentioned functionality):
paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); });
this.model.on('cell:pointerclick', function(evt, x, y) {this.$box.find('textarea').toFront();});
My whole code is as below:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="graph.css">
<script type="text/javascript" src="http://www.jointjs.com/downloads/joint.js" ></script>
<script src="http://www.jointjs.com/downloads/joint.shapes.devs.js" ></script>
<script src="http://www.jointjs.com/downloads/joint.shapes.devs.min.js" ></script>
</head>
<title>Test</title>
<body>
<div id="myholder"></div>
</body>
<script>
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#myholder'),
width: 1500,
height: 700,
model: graph
});
// Create a custom element.
// ------------------------
joint.shapes.html = {};
joint.shapes.html.Element = joint.shapes.basic.Rect.extend({
defaults: joint.util.deepSupplement({
type: 'html.Element',
attrs: {
rect: { stroke: 'none', 'fill-opacity': 0 }
}
}, joint.shapes.basic.Rect.prototype.defaults)
});
// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------
joint.shapes.html.ElementView = joint.dia.ElementView.extend({
template: [
'<div class="html-element">',
'<button class="delete">x</button>',
'<span id="lbl" value="Please write here"></span>',
'<textarea id="txt" type="text" value="Please write here"></textarea>',
'</div>'
].join(''),
initialize: function() {
_.bindAll(this, 'updateBox');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
// Prevent paper from handling pointerdown.
this.$box.find('input,select').on('mousedown click', function(evt) { evt.stopPropagation(); });
// This is an example of reacting on the input change and storing the input data in the cell model.
this.$box.find('textarea').on('change', _.bind(function(evt) {
this.model.set('textarea', $(evt.target).val());
}, this));
this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
// Update the box position whenever the underlying model changes.
this.model.on('change', this.updateBox, this);
// Remove the box when the model gets removed from the graph.
this.model.on('remove', this.removeBox, this);
this.updateBox();
},
render: function() {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.paper.$el.prepend(this.$box);
this.updateBox();
return this;
},
updateBox: function() {
// Set the position and dimension of the box so that it covers the JointJS element.
var bbox = this.model.getBBox();
// Example of updating the HTML with a data stored in the cell model.
paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); });
this.$box.find('span').text(this.model.get('textarea'));
this.model.on('cell:pointerclick', function(evt, x, y) { this.$box.find('textarea').toFront(); });
this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
},
removeBox: function(evt) {
this.$box.remove();
}
});
// Create JointJS elements and add them to the graph as usual.
// -----------------------------------------------------------
var el1 = new joint.shapes.html.Element({
position: { x: 600, y: 250 },
size: { width: 200, height: 100 },
inPorts: ['in'],
outPorts: ['out'],
attrs: {
'.inPorts circle': { fill: 'gray'},
'.outPorts circle': { fill: 'gray'}
},
textarea: 'Start writing'});
graph.addCells([el1]);
paper.on('cell:pointerdblclick', function(cellView, evt, x, y) {
var el2 = new joint.shapes.html.Element({ position: { x: 600, y: 400 }, size: { width: 200, height: 100 }, textarea: 'Start writing'});
var l = new joint.dia.Link({
source: { id: el1.id },
target: { id: el2.id },
attrs: { '.connection': { 'stroke-width': 1, stroke: 'gray' } }
});
graph.addCells([el2, l]);
});
</script>
</html>
I have searched a lot for answers to these problems but I was not successful finding simple and comprehensive ones.
Any help will be appreciated.
Thanks.
I am also new to jointJs and stuck with same problem and found this thread. I have tried and worked successfully.
You have to customize css of element to get better view. Go to working with ports for more work with ports.
Here's the code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://www.jointjs.com/downloads/joint.min.css">
<style type="text/css">
#myholder .html-element{
position: absolute;
margin-left: 8px;
padding: 5px 0 10px 0;
background-color: #fff;
border: 1px solid #eee;
border-radius: 5px;
pointer-events: none;
-webkit-user-select: none;
}
</style>
<script type="text/javascript" src="http://www.jointjs.com/downloads/joint.min.js" ></script>
</head>
<title>Test</title>
<body>
<div id="myholder"></div>
</body>
<script>
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#myholder'),
width: 1500,
height: 700,
model: graph
});
// Create a custom element.
// ------------------------
joint.shapes.html = {};
joint.shapes.html.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '<g class="rotatable"><g class="scalable"><rect/></g><g class="inPorts"/><g class="outPorts"/></g>',
portMarkup: '<g class="port<%= id %>"><circle/></g>',
defaults: joint.util.deepSupplement({
type: 'html.Element',
size: { width: 100, height: 80 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: false },
rect: {
stroke: 'none', 'fill-opacity': 0, width: 150, height: 250,
},
circle: {
r: 6, //circle radius
magnet: true,
stroke: 'black'
},
'.inPorts circle': { fill: 'green', magnet: 'passive', type: 'input'},
'.outPorts circle': { fill: 'red', type: 'output'}
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function (portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portCircleSelector = portSelector + '>circle';
attrs[portCircleSelector] = { port: { id: portName || _.uniqueId(type), type: type } };
attrs[portSelector] = { ref: 'rect', 'ref-y': (index + 0.5) * (1 / total) };
if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; }
return attrs;
}
}));
// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------
joint.shapes.html.ElementView = joint.dia.ElementView.extend({
template: [
'<div class="html-element">',
'<button class="delete">x</button>',
'<span id="lbl" value="Please write here"></span>',
'<textarea id="txt" type="text" value="Please write here"></textarea>',
'</div>'
].join(''),
initialize: function() {
_.bindAll(this, 'updateBox');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
// Prevent paper from handling pointerdown.
this.$box.find('input,select').on('mousedown click', function(evt) { evt.stopPropagation(); });
// This is an example of reacting on the input change and storing the input data in the cell model.
this.$box.find('textarea').on('change', _.bind(function(evt) {
this.model.set('textarea', $(evt.target).val());
}, this));
this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
// Update the box position whenever the underlying model changes.
this.model.on('change', this.updateBox, this);
// Remove the box when the model gets removed from the graph.
this.model.on('remove', this.removeBox, this);
this.updateBox();
this.listenTo(this.model, 'process:ports', this.update);
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
},
render: function() {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.paper.$el.prepend(this.$box);
// this.paper.$el.mousemove(this.onMouseMove.bind(this)), this.paper.$el.mouseup(this.onMouseUp.bind(this));
this.updateBox();
return this;
},
renderPorts: function () {
var $inPorts = this.$('.inPorts').empty();
var $outPorts = this.$('.outPorts').empty();
var portTemplate = _.template(this.model.portMarkup);
_.each(_.filter(this.model.ports, function (p) { return p.type === 'in' }), function (port, index) {
$inPorts.append(V(portTemplate({ id: index, port: port })).node);
});
_.each(_.filter(this.model.ports, function (p) { return p.type === 'out' }), function (port, index) {
$outPorts.append(V(portTemplate({ id: index, port: port })).node);
});
},
update: function () {
// First render ports so that `attrs` can be applied to those newly created DOM elements
// in `ElementView.prototype.update()`.
this.renderPorts();
joint.dia.ElementView.prototype.update.apply(this, arguments);
},
updateBox: function() {
// Set the position and dimension of the box so that it covers the JointJS element.
var bbox = this.model.getBBox();
// Example of updating the HTML with a data stored in the cell model.
// paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); });
this.$box.find('span').text(this.model.get('textarea'));
this.model.on('cell:pointerclick', function(evt, x, y) { this.$box.find('textarea').toFront(); });
this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
},
removeBox: function(evt) {
this.$box.remove();
}
});
// Create JointJS elements and add them to the graph as usual.
// -----------------------------------------------------------
var el1 = new joint.shapes.html.Element({
position: { x: 600, y: 250 },
size: { width: 170, height: 100 },
inPorts: ['in'],
outPorts: ['out'],
textarea: 'Start writing'
});
var el2 = new joint.shapes.html.Element({
position: { x: 600, y: 400 },
size: { width: 170, height: 100 },
inPorts: ['in'],
outPorts: ['out'],
textarea: 'Start writing'
});
graph.addCells([el1, el2]);
</script>
</html>
I have asked a question that no one has answered it. It was how I can make the textarea disappear when I click on the blank paper and appear when I click on the cell: First I thought I have to solve it through the jsonJS events inside the javascript. But I found out that there is a very simple solution for this. I just need to use the hover function in css styling and change the opacity from 0 to 1 when you hover over the box (in your css file) :
.html-element textarea {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60px;
width: 150px;
border: none;
color: #333;
background-color: white;
padding: 5px;
margin: 5px;
opacity:0;
}
.html-element textarea:hover {
opacity:1;
}
rzkmr's answer worked for me, +1'd his response. (Thank you!)
In his example, to allow the textarea to be used, add this to the css:
.html-element select,
.html-element input,
.html-element textarea,
.html-element button {
/* Enable mouse interaction. */
pointer-events: auto;
}

Categories