I have two groups of quiz.
The first group is correct but the second group is not showing the line between two points.
The users click the point on the left and click the point on the right, then JavaScript creates a "canvas" line from the first element to the second element. (I apologise for my english, it's my second language)

(function($) {
$.fn.connect = function(param) {
var _canvas;
var _ctx;
var _lines = new Array(); //This array will store all lines (option)
var _me = this;
var _parent = param || document;
var _lengthLines = $(_parent + ' .group1 .node').length;
var _selectFirst = null;
//Initialize Canvas object
_canvas = $('<canvas/>')
.attr('width', $(_me).width())
.attr('height', $(_me).height())
.css('position', 'absolute');
$(_parent).prepend(_canvas);
//$(_canvas).insertBefore(_parent);
this.drawLine = function(option) {
//It will push line to array.
_lines.push(option);
this.connect(option);
};
this.drawAllLine = function(option) {
/*Mandatory Fields------------------
left_selector = '.class',
data_attribute = 'data-right',
*/
if (option.left_selector != '' && typeof option.left_selector !== 'undefined' && $(option.left_selector).length > 0) {
$(option.left_selector).each(function(index) {
var option2 = new Object();
$.extend(option2, option);
option2.left_node = $(this).attr('id');
option2.right_node = $(this).data(option.data_attribute);
if (option2.right_node != '' && typeof option2.right_node !== 'undefined') {
_me.drawLine(option2);
}
});
}
};
//This Function is used to connect two different div with a dotted line.
this.connect = function(option) {
_ctx = _canvas[0].getContext('2d');
//
_ctx.beginPath();
try {
var _color;
var _dash;
var _left = new Object(); //This will store _left elements offset
var _right = new Object(); //This will store _right elements offset
var _error = (option.error == 'show') || false;
/*
option = {
left_node - Left Element by ID - Mandatory
right_node - Right Element ID - Mandatory
status - accepted, rejected, modified, (none) - Optional
style - (dashed), solid, dotted - Optional
horizantal_gap - (0), Horizantal Gap from original point
error - show, (hide) - To show error or not
width - (2) - Width of the line
}
*/
if (option.left_node != '' && typeof option.left_node !== 'undefined' && option.right_node != '' && typeof option.right_node !== 'undefined' && $(option.left_node).length > 0 && $(option.right_node).length > 0) {
//To decide colour of the line
switch (option.status) {
case 'accepted':
_color = '#0969a2';
break;
case 'rejected':
_color = '#e7005d';
break;
case 'modified':
_color = '#bfb230';
break;
case 'none':
_color = 'grey';
break;
default:
_color = 'grey';
break;
}
//To decide style of the line. dotted or solid
switch (option.style) {
case 'dashed':
_dash = [4, 2];
break;
case 'solid':
_dash = [0, 0];
break;
case 'dotted':
_dash = [4, 2];
break;
default:
_dash = [4, 2];
break;
}
/*
console.log($(option.left_node));
$(option.left_node)
$(option.right_node).data('connect',true);
*/
//If left_node is actually right side, following code will switch elements.
$(option.right_node).each(function(index, value) {
_left_node = $(option.left_node);
_right_node = $(value);
_left_node.attr('data-connect', true);
_right_node.attr('data-connect', true);
if (_left_node.offset().left >= _right_node.offset().left) {
_tmp = _left_node
_left_node = _right_node
_right_node = _tmp;
}
//Get Left point and Right Point
_left.x = _left_node.offset().left + _left_node.outerWidth();
_left.y = _left_node.offset().top + (_left_node.outerHeight() / 2);
_right.x = _right_node.offset().left;
_right.y = _right_node.offset().top + (_right_node.outerHeight() / 2);
//Create a group
//var g = _canvas.group({strokeWidth: 2, strokeDashArray:_dash});
//Draw Line
var _gap = option.horizantal_gap || 0;
_ctx.moveTo(_left.x, _left.y);
if (_gap != 0) {
_ctx.lineTo(_left.x + _gap, _left.y);
_ctx.lineTo(_right.x - _gap, _right.y);
}
_ctx.lineTo(_right.x, _right.y);
if (!_ctx.setLineDash) {
_ctx.setLineDash = function() {}
} else {
_ctx.setLineDash(_dash);
}
_ctx.lineWidth = option.width || 2;
_ctx.strokeStyle = _color;
_ctx.stroke();
});
//option.resize = option.resize || false;
} else {
if (_error) alert('Mandatory Fields are missing or incorrect');
}
} catch (err) {
if (_error) alert('Mandatory Fields are missing or incorrect');
}
//console.log(_canvas);
};
//It will redraw all line when screen resizes
$(window).resize(function() {
console.log(_me);
_me.redrawLines();
});
$(_parent + ' .group1 .node span').click(function() {
//console.log($(this).attr('data-connect'));
//[data-use="false"]
_this = this;
if ($(_this).attr('data-connect') != 'true' && $(_this).attr('data-use') == 'false') {
$(_parent + ' .group1 .node span').attr('data-use', 'false');
$(_this).attr('data-use', 'true');
_selectFirst = _this;
} else if ($(_this).attr('data-connect') == 'true') {
//console.log($(this).attr('data-id'));
//console.log(entry);
_lines.forEach(function(entry, index) {
if ($(_this).attr('data-id') == entry.id_left) {
$(entry.left_node).attr('data-use', 'false').attr('data-connect', 'false')
$(entry.right_node).attr('data-use', 'false').attr('data-connect', 'false')
_lines.splice(index, 1)
}
});
_me.redrawLines();
}
});
$(_parent + ' .group2 .node span[data-use="false"]').click(function() {
if ($(_parent + ' .group1 .node span[data-use="true"]').length == 1 && _selectFirst != null) {
if ($(this).attr('data-connect') != 'true') {
_me.drawLine({
id_left: $(_selectFirst).attr('data-id'),
id_right: $(this).attr('data-id'),
left_node: _selectFirst,
right_node: this,
horizantal_gap: 10,
error: 'show',
width: 1,
status: 'accepted'
});
$(_selectFirst).attr('data-use', 'false');
$(_selectFirst).attr('data-connect', 'true');
$(this).attr('data-use', 'false');
$(this).attr('data-connect', 'true');
}
}
});
this.redrawLines = function() {
_ctx.clearRect(0, 0, $(_me).width(), $(_me).height());
_lines.forEach(function(entry) {
entry.resize = true;
_me.connect(entry);
});
};
return this;
};
}(jQuery));
.clearfix {
clear: both;
}
body {
padding: 0px;
margin: 0px;
}
.nodes {
width: 500px
}
.node {
width: 100px;
background: #ddd;
color: #fff;
margin-bottom: 10px;
}
.group1 span {
background: #666;
border-radius: 50%;
width: 10px;
height: 10px;
margin-top: 5px;
}
.group2 span {
border: 1px solid #666;
border-radius: 50%;
width: 10px;
height: 10px;
margin-top: 5px;
}
.node span:hover {
background: #ff0000;
cursor: pointer;
}
.group1 {
float: left;
}
.group2 {
float: right;
}
.group2 .node span {
float: left;
position: relative;
left: -15px;
}
.group1 .node span {
float: right;
position: relative;
right: -15px;
}
.node span[data-connect=true] {
background: #ff00ff !important;
}
.node span[data-use=true] {
background: #ff0000 !important;
}
<div id="parentNodes_11">
<div class="nodes">
<div class="group1">
<div class="node">1<span class="node1" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">2 <span class="node2" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">3 <span class="node3" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="group2">
<div class="node">A <span class="node4" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">B <span class="node5" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">C <span class="node6" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<br>
<div id="parentNodes_12">
<div class="nodes">
<div class="group1">
<div class="node">1<span class="node1" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">2 <span class="node2" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">3 <span class="node3" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="group2">
<div class="node">A <span class="node4" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">B <span class="node5" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">C <span class="node6" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#parentNodes_11 .nodes').connect('#parentNodes_11');
$('#parentNodes_12 .nodes').connect('#parentNodes_12');
});
</script>
This is due to the use of absolute coordinates for lines instead of relative ones, so your lines doesn't fit on the canvas.
You can just do the parent offset adjustment and it will work like this:
(function($) {
$.fn.connect = function(param) {
var _canvas;
var _ctx;
var _lines = new Array(); //This array will store all lines (option)
var _me = this;
var _parent = param || document;
var _lengthLines = $(_parent + ' .group1 .node').length;
var _selectFirst = null;
//Initialize Canvas object
_canvas = $('<canvas/>')
.attr('width', $(_me).width())
.attr('height', $(_me).height())
.css('position', 'absolute');
$(_parent).prepend(_canvas);
//$(_canvas).insertBefore(_parent);
this.drawLine = function(option) {
//It will push line to array.
_lines.push(option);
this.connect(option);
};
this.drawAllLine = function(option) {
/*Mandatory Fields------------------
left_selector = '.class',
data_attribute = 'data-right',
*/
if (option.left_selector != '' && typeof option.left_selector !== 'undefined' && $(option.left_selector).length > 0) {
$(option.left_selector).each(function(index) {
var option2 = new Object();
$.extend(option2, option);
option2.left_node = $(this).attr('id');
option2.right_node = $(this).data(option.data_attribute);
if (option2.right_node != '' && typeof option2.right_node !== 'undefined') {
_me.drawLine(option2);
}
});
}
};
//This Function is used to connect two different div with a dotted line.
this.connect = function(option) {
_ctx = _canvas[0].getContext('2d');
//
_ctx.beginPath();
try {
var _color;
var _dash;
var _left = new Object(); //This will store _left elements offset
var _right = new Object(); //This will store _right elements offset
var _error = (option.error == 'show') || false;
/*
option = {
left_node - Left Element by ID - Mandatory
right_node - Right Element ID - Mandatory
status - accepted, rejected, modified, (none) - Optional
style - (dashed), solid, dotted - Optional
horizantal_gap - (0), Horizantal Gap from original point
error - show, (hide) - To show error or not
width - (2) - Width of the line
}
*/
if (option.left_node != '' && typeof option.left_node !== 'undefined' && option.right_node != '' && typeof option.right_node !== 'undefined' && $(option.left_node).length > 0 && $(option.right_node).length > 0) {
//To decide colour of the line
switch (option.status) {
case 'accepted':
_color = '#0969a2';
break;
case 'rejected':
_color = '#e7005d';
break;
case 'modified':
_color = '#bfb230';
break;
case 'none':
_color = 'grey';
break;
default:
_color = 'grey';
break;
}
//To decide style of the line. dotted or solid
switch (option.style) {
case 'dashed':
_dash = [4, 2];
break;
case 'solid':
_dash = [0, 0];
break;
case 'dotted':
_dash = [4, 2];
break;
default:
_dash = [4, 2];
break;
}
/*
console.log($(option.left_node));
$(option.left_node)
$(option.right_node).data('connect',true);
*/
//If left_node is actually right side, following code will switch elements.
$(option.right_node).each(function(index, value) {
_left_node = $(option.left_node);
_right_node = $(value);
_left_node.attr('data-connect', true);
_right_node.attr('data-connect', true);
if (_left_node.offset().left >= _right_node.offset().left) {
_tmp = _left_node
_left_node = _right_node
_right_node = _tmp;
}
//Get Left point and Right Point
_left.x = _left_node.offset().left + _left_node.outerWidth();
_left.y = _left_node.offset().top + (_left_node.outerHeight() / 2) - _left_node.parents('.nodes').offset().top;
_right.x = _right_node.offset().left;
_right.y = _right_node.offset().top + (_right_node.outerHeight() / 2) - _right_node.parents('.nodes').offset().top;
//Create a group
//var g = _canvas.group({strokeWidth: 2, strokeDashArray:_dash});
//Draw Line
var _gap = option.horizantal_gap || 0;
_ctx.moveTo(_left.x, _left.y);
if (_gap != 0) {
_ctx.lineTo(_left.x + _gap, _left.y);
_ctx.lineTo(_right.x - _gap, _right.y);
}
_ctx.lineTo(_right.x, _right.y);
if (!_ctx.setLineDash) {
_ctx.setLineDash = function() {}
} else {
_ctx.setLineDash(_dash);
}
_ctx.lineWidth = option.width || 2;
_ctx.strokeStyle = _color;
_ctx.stroke();
});
//option.resize = option.resize || false;
} else {
if (_error) alert('Mandatory Fields are missing or incorrect');
}
} catch (err) {
if (_error) alert('Mandatory Fields are missing or incorrect');
}
//console.log(_canvas);
};
//It will redraw all line when screen resizes
$(window).resize(function() {
console.log(_me);
_me.redrawLines();
});
$(_parent + ' .group1 .node span').click(function() {
//console.log($(this).attr('data-connect'));
//[data-use="false"]
_this = this;
if ($(_this).attr('data-connect') != 'true' && $(_this).attr('data-use') == 'false') {
$(_parent + ' .group1 .node span').attr('data-use', 'false');
$(_this).attr('data-use', 'true');
_selectFirst = _this;
} else if ($(_this).attr('data-connect') == 'true') {
//console.log($(this).attr('data-id'));
//console.log(entry);
_lines.forEach(function(entry, index) {
if ($(_this).attr('data-id') == entry.id_left) {
$(entry.left_node).attr('data-use', 'false').attr('data-connect', 'false')
$(entry.right_node).attr('data-use', 'false').attr('data-connect', 'false')
_lines.splice(index, 1)
}
});
_me.redrawLines();
}
});
$(_parent + ' .group2 .node span[data-use="false"]').click(function() {
if ($(_parent + ' .group1 .node span[data-use="true"]').length == 1 && _selectFirst != null) {
if ($(this).attr('data-connect') != 'true') {
_me.drawLine({
id_left: $(_selectFirst).attr('data-id'),
id_right: $(this).attr('data-id'),
left_node: _selectFirst,
right_node: this,
horizantal_gap: 10,
error: 'show',
width: 1,
status: 'accepted'
});
$(_selectFirst).attr('data-use', 'false');
$(_selectFirst).attr('data-connect', 'true');
$(this).attr('data-use', 'false');
$(this).attr('data-connect', 'true');
}
}
});
this.redrawLines = function() {
_ctx.clearRect(0, 0, $(_me).width(), $(_me).height());
_lines.forEach(function(entry) {
entry.resize = true;
_me.connect(entry);
});
};
return this;
};
}(jQuery));
.clearfix {
clear: both;
}
body {
padding: 0px;
margin: 0px;
}
.nodes {
width: 500px
}
.node {
width: 100px;
background: #ddd;
color: #fff;
margin-bottom: 10px;
}
.group1 span {
background: #666;
border-radius: 50%;
width: 10px;
height: 10px;
margin-top: 5px;
}
.group2 span {
border: 1px solid #666;
border-radius: 50%;
width: 10px;
height: 10px;
margin-top: 5px;
}
.node span:hover {
background: #ff0000;
cursor: pointer;
}
.group1 {
float: left;
}
.group2 {
float: right;
}
.group2 .node span {
float: left;
position: relative;
left: -15px;
}
.group1 .node span {
float: right;
position: relative;
right: -15px;
}
.node span[data-connect=true] {
background: #ff00ff !important;
}
.node span[data-use=true] {
background: #ff0000 !important;
}
<div id="parentNodes_11">
<div class="nodes">
<div class="group1">
<div class="node">1<span class="node1" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">2 <span class="node2" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">3 <span class="node3" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="group2">
<div class="node">A <span class="node4" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">B <span class="node5" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">C <span class="node6" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<br>
<div id="parentNodes_12">
<div class="nodes">
<div class="group1">
<div class="node">1<span class="node1" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">2 <span class="node2" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">3 <span class="node3" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="group2">
<div class="node">A <span class="node4" data-connect="false" data-id="0" data-use="false"></span></div>
<div class="node">B <span class="node5" data-connect="false" data-id="1" data-use="false"></span></div>
<div class="node">C <span class="node6" data-connect="false" data-id="2" data-use="false"></span></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#parentNodes_11 .nodes').connect('#parentNodes_11');
$('#parentNodes_12 .nodes').connect('#parentNodes_12');
});
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With