fidel fidel - 6 months ago 50
jQuery Question

inserting images in draggable

how can i insert multiple images in multiple separate draggables the problem that im having is that i cannot separate the images inside the draggable when i insert two or more they are "stuck" they are dragged all together.
for some reason the code is not working at all but it does work in my website



var z = 1; //value to make div overlappable

$('#addText').click(function (e) {
/** Make div draggable **/
$('<div />', {
class: 'ui-widget-content',
appendTo: '.container',
draggable: {
containment: 'parent',
start: function( event, ui ) {
$(this).css('z-index', ++z);
}
}
});
});


$(document).on("dblclick", '.text', '.img', function()
{
$(this).hide(); $(this).closest('.item').find('.edit_text', '.img').val($(this).text()).show();
});

$(document).on("click", ".edit_text", ".img", function()
{
return false;
});


$(document).on("click", function()
{
var editingText = $('.edit_text:visible');
if (editingText.length)
{
editingText.hide();
editingText.closest('.item').find('.text', '.img').text($(editingText).val()).show();
}
});


var count = 1;
var selectedDraggable;

ko.bindingHandlers.draggable={
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
$(element).draggable();
$(element).addClass('item' + count);
count++;
$(element).on('click', function () {
selectedDraggable = $(this);
})
}
};


var vm=function(){
var self=this;
self.items=ko.observableArray();
self.textContent = ko.observable('');
self.init=function(){
self.items([]);
}
self.remove=function(item){
console.log(item);
self.items.remove(item);
}
self.addNew = function() {
self.items.push( self.textContent() );
self.textContent('');
}
self.init();
}

ko.applyBindings(new vm());







var reader = new FileReader(),
i = 0,
numFiles = 0,
imageFiles;

// use the FileReader to read image i
// pass `File` at index `i` within `FileList` to `readFile`
function readFile(file) {
reader.readAsDataURL(file)
}

// define function to be run when the File
// reader has finished reading the file
reader.onloadend = function(e) {
// increment `i`
++i;
// make an image and append it to the div
var image = $('<img>').attr('src', e.target.result);
$(image).appendTo('#images');

// if there are more files run the file reader again
if (i < numFiles) {
// pass `File` at index `i` within `FileList` to `readFile`
readFile(imageFiles.item(i));
}
};

$('#go').click(function() {
i = 0;
imageFiles = document.getElementById('files').files
// get the number of files
numFiles = imageFiles.length;
// pass first `File` to `readFile`
readFile(imageFiles.item(i));

});

.container {
width: 500px;
height: 500px;
border: 2px solid;
position: relative;
overflow: auto;
}

<textarea data-bind="value: textContent" Placeholder="Type text to append" rows="4" cols="21"></textarea>&nbsp;&nbsp;&nbsp;
<button data-bind="click: addNew">Create</button></p>

<center> <input type="file" multiple id="files" />

<button id="go" data-bind="click: addNew">Create</button>
<div class="container">
<div data-bind="foreach:items" class="fix_backround">
<div href="#" class="item" data-bind="draggable:true,droppable:true">
<span data-bind="click:$parent.remove">[x]</span><br/><br/>
<center><span class="text" data-bind="text:$data"></span><input class="edit_text"/><div class="img" id="images"></div></center>
</div></div></div><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<link rel="stylesheet"
href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<link rel="stylesheet"
href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>

<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

<script src="http://circletype.labwire.ca/js/circletype.js"></script><script src="http://tympanus.net/Development/Arctext/js/jquery.arctext.js"></script>




Answer

Your 'draggable' binding is on the element inside foreach: items. So, if you want to have draggable images, you should make sure the image data is pushed into items.

What you're actually doing, is appending the images to a nested element inside this draggable container (using jQuery).

To convert this into a "knockout approach", you'll have to:

1. Expose your viewmodel instance to your fileReader, e.g.:

Put it in window (not the best solution, obviously):

var vm = new vm();`
ko.applyBindings(vm);

2. Push an image source to vm.items when it's ready, e.g.:

In your onloadend method:

reader.onloadend = function(e) {
  // ...
  // make an image and append it to the div
  vm.items.push(e.target.result);
  // ...
};

3. Create a src attribute data-bind in your draggable container:

For example:

<div data-bind="foreach:items">
  <div data-bind="draggable:true, droppable:true">
    <img data-bind="attr: {src: $data }" />
  </div>
</div>

I've included a quickly fixed version below, but I'd advice you to either rewrite some of the logic and get rid of as much of the jQuery code as possible, or reconsider if you need knockout at all.

Usually, when you include knockout in a project, you should not influence the DOM unless it's via a knockout custom binding. Messing with the DOM behind knockout's back will most likely get you in to trouble eventually.

var z = 1; //value to make div overlappable

$('#addText').click(function(e) {
  /** Make div draggable **/
  $('<div />', {
    class: 'ui-widget-content',
    appendTo: '.container',
    draggable: {
      containment: 'parent',
      start: function(event, ui) {
        $(this).css('z-index', ++z);
      }
    }
  });
});


$(document).on("dblclick", '.text', '.img', function() {
  $(this).hide();
  $(this).closest('.item').find('.edit_text', '.img').val($(this).text()).show();
});

$(document).on("click", ".edit_text", ".img", function() {
  return false;
});


$(document).on("click", function() {
  var editingText = $('.edit_text:visible');
  if (editingText.length) {
    editingText.hide();
    editingText.closest('.item').find('.text', '.img').text($(editingText).val()).show();
  }
});


var count = 1;
var selectedDraggable;

ko.bindingHandlers.draggable = {
  init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
    $(element).draggable();
    $(element).addClass('item' + count);
    count++;
    $(element).on('click', function() {
      selectedDraggable = $(this);
    })
  }
};


var vm = function() {
  var self = this;
  self.items = ko.observableArray();
  self.textContent = ko.observable('');
  self.init = function() {
    self.items([]);
  }
  self.remove = function(item) {
    console.log(item);
    self.items.remove(item);
  }
  self.addNew = function() {
    self.items.push(self.textContent());
    self.textContent('');
  }
  self.init();
}

var vm = new vm();
ko.applyBindings(vm);







var reader = new FileReader(),
  i = 0,
  numFiles = 0,
  imageFiles;

// use the FileReader to read image i
// pass `File` at index `i` within `FileList` to `readFile`
function readFile(file) {
  reader.readAsDataURL(file)
}

// define function to be run when the File
// reader has finished reading the file
reader.onloadend = function(e) {
  // increment `i`
  ++i;
  // make an image and append it to the div
  vm.items.push(e.target.result);

  // if there are more files run the file reader again
  if (i < numFiles) {
    // pass `File` at index `i` within `FileList` to `readFile`
    readFile(imageFiles.item(i));
  }
};

$('#go').click(function() {
  i = 0;
  imageFiles = document.getElementById('files').files
    // get the number of files
  numFiles = imageFiles.length;
  // pass first `File` to `readFile`
  readFile(imageFiles.item(i));

});
.container {
  width: 500px;
  height: 500px;
  border: 2px solid;
  position: relative;
  overflow: auto;
}
<textarea data-bind="value: textContent" Placeholder="Type text to append" rows="4" cols="21"></textarea>&nbsp;&nbsp;&nbsp;
<button data-bind="click: addNew">Create</button>

<center>
  <input type="file" multiple id="files" />

  <button id="go" data-bind="click: addNew">Create</button>
  <div class="container">
    <div data-bind="foreach:items" class="fix_backround">
      <div href="#" class="item" data-bind="draggable:true,droppable:true">
        <img data-bind="attr: {src: $data }" />
      </div>
    </div>




    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
    <script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/jquery-1.10.2.js"></script>

    <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

    <script src="http://circletype.labwire.ca/js/circletype.js"></script>
    <script src="http://tympanus.net/Development/Arctext/js/jquery.arctext.js"></script>