I am currently using a combination of fancybox thumbnails and buttons (only the toggle size button). By default, the buttons appear in the centre of the viewport, I would like to move this to the bottom right hand corner of the image, essentially appearing attached in the same way the close button is or just below the right corner would also be fine.
I have tried space it relative to the viewport width but it doesn't work. Is there a way to position it relative to the image?
I apologise for the abundance of code - I have no idea what to include and what to disregard, so I've put it all in.
If you look at my website (unfinished but I've uploaded it to help) you can see the issue on gallery one.
Shereewalker.com
Any help would be very much appreciated.
Here is my css
#fancybox-buttons {
position: fixed;
left: 0;
width: 100%;
z-index: 8050;}
#fancybox-buttons.top {top: 10px;}
#fancybox-buttons.bottom {bottom: 10px;}
.fancybox-close {
position: absolute;
top: -18px;
right: -18px;
width: 36px;
height: 36px;
cursor: pointer;
z-index: 8040; }
#fancybox-buttons ul {
width: 36px;
height: 36px;
cursor: pointer;
margin: 0 auto;
list-style: none;}
#fancybox-buttons ul li {
float: left;
margin: 0;
padding: 0;}
And my javascript
jQuery(document).ready(function ($) {
$(".fancybox").fancybox({
prevEffect : 'none',
nextEffect : 'none',
// API options
helpers : {
title : {
type: 'outside'
},
buttons: {},
thumbs: {
width : 10,
height : 10
}
}
}); // fancybox
}); // ready
And even more javascript
(function ($) {
//Shortcut for fancyBox object
var F = $.fancybox;
//Add helper object
F.helpers.buttons = {
defaults : {
skipSingle : false, // disables if gallery contains single image
position : 'top', // 'top' or 'bottom'
tpl : '<div id="fancybox-buttons"><ul><li><a class="btnToggle" title="Toggle size" href="javascript:;"></a></li></ul></div>'
},
list : null,
buttons: null,
beforeLoad: function (opts, obj) {
//Remove self if gallery do not have at least two items
if (opts.skipSingle && obj.group.length < 2) {
obj.helpers.buttons = false;
obj.closeBtn = true;
return;
}
//Increase top margin to give space for buttons
obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30;
},
onPlayStart: function () {
if (this.buttons) {
this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn');
}
},
onPlayEnd: function () {
if (this.buttons) {
this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn');
}
},
afterShow: function (opts, obj) {
var buttons = this.buttons;
if (!buttons) {
this.list = $(opts.tpl).addClass(opts.position).appendTo('body');
buttons = {
prev : this.list.find('.btnPrev').click( F.prev ),
next : this.list.find('.btnNext').click( F.next ),
play : this.list.find('.btnPlay').click( F.play ),
toggle : this.list.find('.btnToggle').click( F.toggle ),
close : this.list.find('.btnClose').click( F.close )
}
}
//Prev
if (obj.index > 0 || obj.loop) {
buttons.prev.removeClass('btnDisabled');
} else {
buttons.prev.addClass('btnDisabled');
}
//Next / Play
if (obj.loop || obj.index < obj.group.length - 1) {
buttons.next.removeClass('btnDisabled');
buttons.play.removeClass('btnDisabled');
} else {
buttons.next.addClass('btnDisabled');
buttons.play.addClass('btnDisabled');
}
this.buttons = buttons;
this.onUpdate(opts, obj);
},
onUpdate: function (opts, obj) {
var toggle;
if (!this.buttons) {
return;
}
toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn');
//Size toggle button
if (obj.canShrink) {
toggle.addClass('btnToggleOn');
} else if (!obj.canExpand) {
toggle.addClass('btnDisabled');
}
},
beforeClose: function () {
if (this.list) {
this.list.remove();
}
this.list = null;
this.buttons = null;
}
};
}(jQuery));
If you want to move the toggle button only, you actually need to clone it rather than moving it.
Based on this answer https://stackoverflow.com/a/17888534/1055987, we could tweak it into this :
CSS
/* hide the actual buttons helper */
#fancybox-buttons {
display: none;
}
/* position the clone : notice the class "clone" */
.clone {
position: absolute;
top: 5px;
right: 0;
}
.btnToggle.clone {
background-position: 3px -60px;
border-left: 1px solid #111;
border-right: 1px solid #3e3e3e;
width: 35px;
height: 35px;
background-image: url("{your path}/helpers/fancybox_buttons.png");
background-color: #333;
}
.clone.btnToggleOn {
background-position: -27px -60px;
}
Then the jQuery code :
jQuery(document).ready(function ($) {
$(".fancybox").fancybox({
helpers: {
title: {
type: 'inside'
},
buttons: {} // we need this to clone
},
afterLoad: function () {
// make sure we have a title
this.title = this.title ? this.title : " ";
},
afterShow: function () {
// wait for the buttons helper
setTimeout(function () {
$("#fancybox-buttons")
.find(".btnToggle")
.clone(true, true) // clone with data and events
.addClass("clone") // add class "clone"
.appendTo(".fancybox-title") // append it to the title
.fadeIn(); // show it nicely
}, 100); //setTimeout
}, // afterShow
onUpdate: function () {
var toggle = $(".btnToggle.clone").removeClass('btnDisabled btnToggleOn');
if (this.canShrink) {
toggle.addClass('btnToggleOn');
} else if (!this.canExpand) {
toggle.addClass('btnDisabled');
}
}
}); // fancybox
}); // ready
See JSFIDDLE
The toggle size button (and thumbnails) and hard to align because they are in separate full-width containers. This markup is generated by FancyBox for the gallery slideshow.
It looks like this:
<body>
<div class="fancybox-wrap">
<div class="fancybox-overlay">
<div id="fancybox-buttons">
<div id="fancybox-thumbs">
The .fancybox-wrap contains the gallery image and #fancybox-buttons contains the toggle size button.
Luckily, the OP was creating a template (tpl) for the toggle size button... but was injecting it into the <body> so it was unaware of the content of the .fancybox-wrap.
To fix this just change this line:
this.list = $(opts.tpl).addClass(opts.position).appendTo('body');
To this:
this.list = $(opts.tpl).addClass(opts.position).appendTo('.fancybox-wrap');
This just puts the buttons inside the same container as the gallery image (which is what we want to align too).
Related
I`m trying to put an image in place of dojo button. I am able to add the image, as background, but, the outline of the button is visible. I would want ot show the image only. What should I do?
my code is follows.
css:
.EditButtonWidgetImage {
background-image: url("EditButton/images/edit.png");
background-position: center;
background-repeat: no-repeat;
height: 25px;
width: 25px;
}
javascript:
var infoTableContainer = dojo.create("div", null, map.container);
var x = 200 - map.position.x;
var y = 50 - map.position.y;
this.InfoTable = new FloatingPane({
title : "<b>Editor</b>",
resizable: true,
doLayout: true,
dockable: false,
closable: true,
//constrainToContainer: true,
'class': "EditWidgetContainer",
style: "left:"+x+"px;top:"+y+"px;padding:0px"
}, infoTableContainer);
//dojo.attr(infoTable, 'class', 'TableInfoWidgetContainer'); //ie8에서 class 예약어 처리로 인해 변경
dojo.connect(this.InfoTable, 'close', lang.hitch(this, function() {
//this.InfoTable.destroy();
//console.log('infoGrid (infotable.destroy)=',this.InfoGrid);
if (this.InfoGrid) {
//this.InfoGrid.destroyRecursive(true);
this.InfoGrid.destroy();
this.InfoGrid = null;
this.InfoGrid = undefined;
}
this.InfoTable = null;
this.InfoTable = undefined;
}));
//Border생성
var border = new BorderContainer({
gutters: false,
design: 'headline',
style: "height:100%;width:100%;"
})
//검색옵션 생성
var cpT = ContentPane({
region: "top",
title: "검색 옵션",
style: "height:auto;width:100%;"
});
this.cboService = new ComboBox({
title: '서비스 : ',
searchAttr: "SVC_NM",
style: "width:120px;"
});
this.cboLayer = new ComboBox({
searchAttr: "LYR_NM",
style: "width:120px;"
});
var btnResult = new Button({
iconClass : "EditButtonWidgetImage",
style: "width:40px;margin-left:4px;"
});
dojo.place('<label class="widget_field_label" style=width:70px; >편집대상 : </label>', cpT.domNode);
cpT.addChild(this.cboService);
dojo.place('<label class="widget_field_label" style=width:80px;>참조레이어 : </label>', cpT.domNode);
cpT.addChild(this.cboLayer);
cpT.addChild(btnResult);
border.addChild(cpT);
border.placeAt(this.InfoTable.containerNode);
border.startup();
this.InfoTable.startup();
If your using "dijit/form/Button" just include following class and you will see the result.
Here i have overridden the button class. Make sure to limit the scope to specific button only.
.claro .dijitButton .dijitButtonNode {
background-color: transparent;
border: none;
box-shadow: none;
}
I had faced with something similar, the solution that worked for me was to remove the dijitButtonNode class. But then, that would leave you with a image and no indication that it's a button. Is that what you really want?
domClass.remove(btnResult.domNode.childNodes[0], "dijitButtonNode")
Alternatively, you could simple add and img tag, and add a click event to it.
Basically you need to overwrite class .dijitButtonNode from dojo theme (in this case claro).
You can use the following CSS as starting point:
https://jsfiddle.net/zzot4zur/
.claro .dijitButton .dijitButtonNode {
background-color: transparent;
border: none;
box-shadow: none;
background-image: url("http://www.nuflowwidebay.com.au/wp-content/uploads/2015/10/expences-button-png-hi.png");
background-size: 75px 30px;
background-repeat: no-repeat;
width: 75px;
height: 30px;
}
require(["dijit/form/Button", "dojo/dom", "dojo/domReady!"], function(Button, dom) {
// Create a button programmatically:
var myButton = new Button({
label: "Click me!",
onClick: function() {
// Do something:
dom.byId("result1").innerHTML += "Thank you! ";
}
}, "progButtonNode").startup();
});
<button id="progButtonNode" type="button"></button>
<div id="result1"></div>
I am trying to create two sets of play/pause controls for a video using jquery and css. The first set is on the first screen in a large size, and the second set is in a fixed location in the viewport as the user scrolls down, this is so the user can listen to the audio and operate the controls as they view the website without having to scroll to the top. When the users clicks pause, the video pauses and fades, the pause button fades, and the play button becomes full opacity, and the opposite happens when the user clicks play. I have this working for the first set in the jsfiddle and code below, however I have been trying for the past few hours to find a way to make these changes happen with both sets of controls so both sets stay in sync (ie: when one pause button fades, the one in the second set does as well) and have not been able to make much progress.
Here is a jsfiddle (edited, was missing some css) of the first set working, and the jquery:
Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
get: function() {
return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
}
})
var vid = document.getElementById("myVideo"),
pauseButton = document.getElementById("vidpause"),
playButton = document.getElementById("vidplay");
var vid = document.getElementById("myVideo");
function vidFade() {
vid.classList.add("stopfade");
}
pauseButton.addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.paused) {
vid.play();
vidpause.classList.add("full-button");
vidpause.classList.remove("fade-button");
vidplay.classList.add("fade-button");
vidplay.classList.remove("full-button");
} else {
vid.pause();
vidpause.classList.add("fade-button");
vidpause.classList.remove("full-button")
vidplay.classList.add("full-button");
vidplay.classList.remove("fade-button")
}
})
playButton.addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.playing) {
vid.pause();
vidplay.classList.add("full-button");
vidplay.classList.remove("fade-button");
vidpause.classList.add("fade-button");
vidpause.classList.remove("full-button");
} else {
vid.play();
vidplay.classList.add("fade-button");
vidplay.classList.remove("full-button")
vidpause.classList.add("full-button");
vidpause.classList.remove("fade-button")
}
})
I know that getElementById will only work with one element, to get the second set working with the first, I have tried using getElementByClassName (not shown) or querySelectorAll (below).
Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
get: function() {
return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
}
})
var vid = document.getElementById("myVideo");
function vidFade() {
vid.classList.add("stopfade");
}
var pauseButton = document.querySelectorAll(".vidpause");
var i;
for (i = 0; i < pauseButton.length; i++) {
pauseButton[i].addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.paused) {
vid.play();
vidpause.classList.toggleClass("full-button");
vidpause.classList.remove("fade-button");
vidplay.classList.add("fade-button");
vidplay.classList.remove("full-button");
}
else {
vid.pause();
vidpause.classList.add("fade-button");
vidpause.classList.remove("full-button")
vidplay.classList.add("full-button");
vidplay.classList.remove("fade-button")
}
})
}
var playButton = document.querySelectorAll(".vidplay");
var i;
for (i = 0; i < pauseButton.length; i++) {
playButton[i].addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.playing) {
vid.pause();
vidplay.classList.add("full-button");
vidplay.classList.remove("fade-button");
vidpause.classList.add("fade-button");
vidpause.classList.remove("full-button");
} else {
vid.play();
vidplay.classList.add("fade-button");
vidplay.classList.remove("full-button")
vidpause.classList.add("full-button");
vidpause.classList.remove("fade-button")
}
})
}
When I try the above and variations of it, the chrome console gives me an error of "vidpause is undefined". I have been thinking maybe there is an issue with the order I am calling my elements in, or trying to loop the array (?) or trying to change classes while calling classes but ... I am stumped.
Any advice on this would be very helpful, I am pretty new to jquery.
First querySelectorAll returns a NodeList, so it does not have the classList property thus the error.
You need to iterate over the list and set the property. You can also simplify the code set by adding a common class video-play and video-pause to all the play and pause buttons
Object.defineProperty(HTMLMediaElement.prototype, 'playing', {
get: function() {
return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2);
}
})
var vid = document.getElementById("myVideo");
function vidFade() {
vid.classList.add("stopfade");
}
function fadeInOut(fadeIn, fadeOut) {
[].forEach.call(fadeIn, function(el) {
el.classList.add('full-button');
el.classList.remove('fade-button');
});
[].forEach.call(fadeOut, function(el) {
el.classList.remove('full-button');
el.classList.add('fade-button');
});
};
var pauseButtons = document.querySelectorAll(".video-pause");
var playButtons = document.querySelectorAll(".video-play");
[].forEach.call(document.querySelectorAll(".video-play, .video-pause"), function(pauseButton) {
pauseButton.addEventListener("click", function(e) {
e.preventDefault();
vid.classList.toggle("stopfade");
if (vid.paused) {
vid.play();
fadeInOut(pauseButtons, playButtons);
} else {
vid.pause();
fadeInOut(playButtons, pauseButtons);
}
})
});
video#myVideo {
transition: 1s opacity;
}
.stopfade {
opacity: .5;
}
.vidplay {
opacity: 0.50;
}
.vidpause {
opacity: 1;
}
/* Play/Pause Main */
.icon-play-main {
position: absolute;
top: 165px;
left: 50px;
width: 0;
height: 0;
border-width: 23px 35px;
border-style: solid;
border-color: transparent transparent transparent #ff0;
/* #666 */
}
.icon-pause-main,
.icon-pause-main:after {
position: absolute;
width: 14px;
height: 45px;
background-color: #ff0;
/* #666 */
}
.icon-pause-main {
top: 165px;
left: 3.5px;
}
.icon-pause-main:after {
content: "";
top: 0;
left: 20px;
}
/* Play/Pause bottom left */
.playpause {
top: 230px;
left: 0px;
position: fixed;
x-index: 510;
}
.icon-play {
position: absolute;
top: 10px;
left: 30px;
width: 0;
height: 0;
border-width: 10px 15px;
border-style: solid;
border-color: transparent transparent transparent #0cf;
/* #666 */
}
.icon-pause,
.icon-pause:after {
position: absolute;
width: 6px;
height: 20px;
background-color: #0cf;
/* #666 */
}
.icon-pause {
top: 10px;
left: 6px;
}
.icon-pause:after {
content: "";
top: 0;
left: 10px;
}
.fade-button {
opacity: 0.50;
}
.full-button {
opacity: 1;
}
<video autoplay loop muted id="myVideo">
<source src="http://hushhushandsecret.com/hhs/jquery/fullpagejs/imgs/flowers.mp4" type="video/mp4">Your browser does not support the video element.
</video>
<a class="video-pause vidpause full-button" href="#"><span class="icon-pause-main"></span></a>
<a class="video-play vidplay fade-button" href="#"><span class="icon-play-main"></span></a>
<div class="playpause">
<a class="full-button" href="#"><span class="video-pause icon-pause"></span></a>
<a class="fade-button" href="#"><span class="video-play icon-play"></span></a>
</div>
in order to convert it to a cleaner jQuery method you will need to do the following:
Add an extra generic class to each of the video controls such as play and pause:
<a id="vidpause" class="full-button" href="#"><span class="icon-pause-main pause"></span></a>
<a id="vidplay" class="fade-button" href="#"><span class="icon-play-main play"></span></a>
<div class="playpause">
<a class="full-button" href="#"><span class="icon-pause pause"></span></a>
<a class="fade-button" href="#"><span class="icon-play play"></span></a>
</div>
Then use jQuery generic class selectors with $(this) to manipulate the video and clicked controls as necessary:
// create a variable for the video element
var vid = $('#myVideo');
// Function to re-uyse repeated code
// Takes a bool playing - is the video playing
// takes element clicked - the video control element clicked
function vidControls(playing, clicked){
// if the video is playing pause it
if(!playing){
vid.get(0).pause();
clicked.parent('a').removeClass('fade-button').addClass('full-button'); // toggle the classes
clicked.parent('a').prev().removeClass('full-button').addClass('fade-button'); // assume pause always before play
}else{ // otherwise play it
vid.get(0).play();
clicked.parent('a').removeClass('full-button').addClass('fade-button'); // toggle the classes
clicked.parent('a').prev().removeClass('fade-button').addClass('full-button'); // assume pause always before play
}
}
// Play button click event
$('.play').click(function(){
// fade the video in/out as necessary
vid.toggleClass('stopfade');
// Re-use repeating code
vidControls(vid.get(0).paused, $(this));
});
// Pause button click event
$('.pause').click(function(){
// fade the video in/out as necessary
vid.toggleClass('stopfade');
// Re-use repeating code:
vidControls(vid.get(0).paused, $(this));
});
Working JSFiddle
I am relatively new to all this so if you see anything I am doing wrong, or anyways to simplify any code please do not hesitate to say.
I have the following code to enlarge the div element:
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function () {
$(this).animate({
width: '100%',
height: '40%'
}, 200);
$('.closePost', this).removeClass('closePostHide');
});
};
$(document).ready(profilePostsClick);
https://jsfiddle.net/jvkhmpbt/
I am wanting to close each div when the cross is clicked, returning it to it's original size and positioning (with height: auto if feasible).
Aslo is there a way to make it so each div opens above the smaller ones? (like the top left div does, i am aware this is because of it's positioning)
Thanks
You can do like following way by adding and removing class
JQuery:
$('.largeBox, .smallBox, .longBox').click(function (e) {
e.preventDefault();
$(this).addClass('increaseSize');
$('.closePost', this).removeClass('closePostHide');
});
$('.glyphicon-remove').click(function (e) {
e.stopPropagation()
$('.glyphicon-remove').parent().parent().removeClass('increaseSize');
$('.closePost', this).addClass('closePostHide');
});
CSS:
.increaseSize{
width: 100%;
height: 40%;
}
Check Fiddle Here.
You could save the animation properties/values in an cache-object and restore them after your animation.
http://jsfiddle.net/jvkhmpbt/4/
var animationResetCache = [];
var saveValues = function (node) {
animationResetCache.push({
node: node,
width: node.css('width'),
height: node.css('height')
});
};
var restoreValues = function (node) {
for (var i = 0; i < animationResetCache.length; ++i) {
var item = animationResetCache[i];
if (item.node.is(node)) {
return item;
}
}
};
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function (e) {
var $this = $(this);
if ($this.hasClass('open')) return;
saveValues($this);
$this.addClass('open').animate({
width: '100%',
height: '40%'
}, 200);
$this.find('.closePost').removeClass('closePostHide');
});
$('.closePost').click(function () {
var $parent = $(this).parent('.largeBox, .smallBox, .longBox');
if ($parent.hasClass('open')) {
var cachedValues = restoreValues($parent);
$parent.animate({
width: cachedValues.width,
height: cachedValues.height
}, function () {
$parent.removeClass('open');
});
$parent.find('.closePost').addClass('closePostHide');
}
});
};
$(document).ready(profilePostsClick);
I think it's easier to use a toggle and do the animation in CSS3
$("img").click(function(){
$(this).toggleClass('expanded');
});
I would suggest to add one more identical class to each of smallBox,largeBox and longBox which will be called parentd to identify parent div and animate it back and add below js:
DEMO
$('.closePost').on('click',function(e)
{
$(this).closest('.parentd')
.animate({
width: '40%',
height: 'auto'
},200).removeAttr('style');
$(this).addClass('closePostHide');
e.stopPropagation();
});
If we continue on Rover his answer, we can use the switchClass function in jQuery Ui. (source)
This function let's you switch the classes of an object, creating an animation in the difference between those classes.
Example code: jsFiddle
<div class="large"></div>
CSS:
.large{
width: 100%;
height: 200px;
background-color: red;
}
.small {
width: 10%;
height: 50px;
background-color:green;
}
JS:
$("div").switchClass("large","small",500);
I am using joint.js in my angular.js application , I have joint.js node in which I am using html
<button class="delete">x</button>
( you can see this in my backbone view template) whenever user clicks on this button, I want to remove the node which works absolutely fine but what I want to improve is that button should appear only when user clicks on its node and when user clicks on paper other than node that cross button should disappear just like
http://jointjs.com/rappid#a3e927c4-9c6b-4159-b14e-920299be8f87
my logic which I thought is to have a class in button's parent div
.html-element button.delete{
display: none;
}
.html-element.showButton button.delete{
display: block;
}
which will be added when user will click on the node and removed when user will click on the paper. but when I do this logic of adding and removing class it works but the functionality of removal of node on cross button stops.
By whole day debugging and altering the code, I have come to this ,that somehow when this function is called
f2:function(){
var self=this;
var elementDiv = $(self.$box).find('button');
elementDiv.parent().removeClass("showButton")
}
the removal of node on cross button click stops.it means the binding of icon to removal function of model is removed. this is the binding
this.$box.find('.delete').on('click', function()
self.model.remove();
});
I hope that this explanation makes some sense. Below is complete code
var graph = new joint.dia.Graph;
var element1=false;
var paper = new joint.dia.Paper({
el: $('#workFlow'),
width: '100%',
height: '98%',
model: graph,
gridSize: 1
});
paper.on('cell:pointerdown',
function(cellView, evt, x, y) {
$scope.cellView=cellView;
cellView.f1();
}
);
paper.on('blank:pointerdown', function(cell) {
$scope.cellView.f2();
});
Backbone View for extending shapes
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,stageType: dataSourceType}
}
}, 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: [
'<span class="glyphicons '+icon+' html-element">',
'<button class="delete">x</button>',
'</span>'
].join(''),
initialize: function() {
var self=this;
_.bindAll(this, 'updateBox');
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.$box = $(_.template(this.template)());
// this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
this.$box.find('.delete').on('click', function(event){
self.model.remove();
});
// 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() {
var self=this;
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.
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();
},
f1:function(){
var self=this;
var elementDiv = $(self.$box).find('button');
elementDiv.parent().addClass("showButton");
},
f2:function(){
var self=this;
var elementDiv = $(self.$box).find('button');
elementDiv.parent().removeClass("showButton")
}
});
var el1 = new joint.shapes.html.Element({ position: { x: $scope.shapeX, y: $scope.shapeY }, size: { width: 40, height: 40 }, label: 'I am HTML', select: 'one' });
graph.addCells([el1]);
If you haven't solved your problem: there is a very simple solution for what you want to do. You 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 button.delete {
color: white;
border: none;
background-color: gray;
border-radius: 20px;
width: 15px;
height: 15px;
line-height: 15px;
text-align: middle;
position: absolute;
top: -5px;
left: -5px;
padding: 0;
margin: 0;
font-weight: bold;
cursor: pointer;
opacity:0;
}
.html-element button.delete:hover {
/*width: 20px;
height: 20px;
line-height: 20px;*/
opacity:1;
}
I have an HTML5 Canvas. When the user double-clicks in a particular region of that canvas, I want a single-field form to appear at that spot, so that the user can edit some text.
My intended effect is similar to this screenshot from Google Docs. I double-clicked on the shape with the "Hello" text, and the editable text field appeared.
I've worked out how to detect the double-click, the mouse location, and the text. But so far I'm using a javascript "prompt(...)" dialog to edit the text, which is not what I want.
I guess I'm looking for something to put in this function to replace prompt:
// let the user edit the text, by showing a popup-field that appears at (x, y)
function editText(x, y, text) {
return prompt('Text:', text);
}
If it is relevant, I'm using jQuery a little.
Apprise didn't seem to do everything you were asking so I wrote this: http://jsfiddle.net/Qj9QR/12/
CSS
.prompt { position: absolute; background-color: #E0ECFF; border-radius: 3px; width: 200px; height: 50px; border: 1px solid #99C0FF }
.prompt textarea { margin: 4px 0 0 4px }
.prompt .hint { position: absolute; bottom: 1px; left: 5px; font-size: 9px; color: #444466 }
JS uses jQuery see fiddle
function prompt(opts){
this.opts = $.extend({}, this.defaults, opts);
this.init();
this.open();
}
prompt.prototype = {
defaults: { x: 0, y: 0, text: 'Type Here' },
init: function(){
this.create();
this.bind();
this.position();
},
bind: function(){
var self = this;
this.el.click(false).find('textarea').bind('keypress', function(e){
if(e.which === 13) self.close(e);
});
$(document).bind('click.prompt', $.proxy(self.close, self));
},
close: function(e){
if(this.opts.close){
this.opts.close.apply(this, arguments);
}
if(!e.isPropagationStopped()){
$(document).unbind('click', this.close);
this.el.remove();
}
},
create: function(){
this.el = $('<div class="prompt" />')
.append('<textarea></textarea>')
.find('textarea').val(this.opts.text)
.end()
.append('<span class="hint">Hint: use Shift-Enter for multiple lines</span>');
},
position: function(){
this.el.css({top: this.opts.y, left: this.opts.x });
},
open: function(){
this.el.appendTo('body');
this.el.show('fast')
.find('textarea').focus().select();
}
};
// IN USE: when you click an LI update some html
$('li').click(function(){
var li = $(this),
pos = li.position();
new prompt({
text: li.html(),
x: pos.left,
y: pos.top + 17,
close: function(e){
var newText = $(e.target).val();
newText && li.html(newText);
}
});
return false;
});
Updated with position and updating element values