Dragover issue in Meteor - drag-and-drop

I've just started learning Meteor (and Templating). I really enjoy it so far. However, I'm running into a weird issue using HTML5 native drag n drop events on a table. Note that I'm not using jQuery events.
I have a table with droppable td and draggable elements.
So my table template looks like this:
<template name="table">
<table>
{{#each row}}
<tr>
{{#each col}}
<td>
{{#each elements}}
{{>element}}
{{/each}}
</td>
{{/each}}
</tr>
{{/each}}
</table>
</template>
Template.tasktable.events({
'dragover td': function(evt) {
evt.preventDefault();
},
'drop td': function(evt) {
evt.preventDefault();
var id = evt.dataTransfer.getData('Text');
Collection.update({_id: id}, {$set: {value: this.value}});
}
});
Then my element template looks like this:
<template name="element">
<div draggable="true">{{value}}</div>
</template>
Template.element.events({
'dragstart': function(evt, tmpl) {
evt.dataTransfer.setData('Text', this._id);
}
});
For some reason that is melting my brain, the drag over event is being followed by a rendering event, as you can see on the dev tool image here: http://cl.ly/image/3O1S2d1j1f1a
This is extremely painful as dragover is being fired a lot and subsequently the dropevent is queued after several seconds. I have no idea where that comes from, it looks like domutils.js is being called.
Hope I'm clear enough.
Thanks so much.
EDIT
I managed to prevent the rendering event to appear, by removing the dragover event from the Template events and adding
$(document).on('dragover', 'td', function(evt) {evt.preventDefault();})
which is jQuery but doesn't get caught by domutils.js or listeners.js from Meteor.

Based on #Cuberto answer in the comments, I've successfully managed to solve the problem by upgrading Meteor with their new upcoming templating engine Blaze UI (which is still work in progress and not released yet).
Blaze UI uses jQuery events, and this seems to fix restyling layout issues mentioned above.
Should you want to permanently upgrade to Blaze UI, you need to run from the terminal:
meteor update --release template-engine-preview-10.1
Should you want to keep using the old templating engine that comes with the current release of Meteor (0.7.0.1), the fix I mentioned in the EDIT of my original post solves it:
$(document).on('dragover', 'td', function(evt) {evt.preventDefault();})

Related

Drop event not firing in Blazor drag and drop

I'm having a strange problem with Blazor...
I had an application where I was using drag and drop and it was working fine using .Net Core 3.1. However the drop event is now not getting fired no matter what I do and I'm at a loss as to why. So I've created a new Blazor project and kept everything as it is in the standard project template, but I've modified the Index.razor page with the following code to see if I can find out what's going wrong:-
#page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
<ul>
<li draggable="true" #ondragstart="OnDragStart" style="background-color:blue;color:white;width:50px;height:50px;">drag me</li>
</ul>
<div dropzone="move" #ondrop="OnDrop" #ondragover:preventDefault style="background-color:green;color:white;width:200px;height:200px;">
and drop me here
</div>
<div>#DragState</div>
#code {
public string DragState = "waiting...";
public void OnDragStart(DragEventArgs dragEventArgs)
{
DragState = "drag started";
}
public void OnDrop(DragEventArgs dragEventArgs)
{
DragState = "item dropped";
}
}
As far as I can see this should work, the drag start event works fine but any browser (FireFox, Chrome etc...) I try the drop event never gets fired.
I'm guessing I must be doing something glaringly wrong somewhere but I cannot see it, so I'm hoping someone else can :-)
Note, I've not changed any other file or setting in the default Blazor project, just this modification to the Index.razor file to test the drag and drop...
You have code to preventDefault for ondragover event but the syntax is wrong. Change your dropzone to
<div dropzone="move" #ondrop="OnDrop" ondragover="event.preventDefault();" style="background-color:green;color:white;width:200px;height:200px;">
and drop me here
</div>
and it should work fine.

is there a way to tell react to dynamically create div if not found

New to react and I'm wondering if there is any work around to get past this error:
_registerComponent(...): Target container is not a DOM element.
EDIT What I'm trying to do is:
I have a react function like:
ReactDOM.render(React.createElement(someFunction,{data:someData}),document.getElementById('someID')
which generates a dom like :
<span>
<ul data-reactid='...'>blahhh</ul>
<div data-reactid='...'>
<div id='some-id1' data-reactid='...'>blahhh</div>
<div id='some-id2'data-reactid='...'>blahhhh</div>
</div>
</span>
Now on the very next line to the previous react call, I have other function which is trying to do stuff with the above created div:
ReactDOM.render(React.createElement(someOtherReactFunction, { somePram: 'ImParam'}), document.getElementById('some-id1'));
This gives me:
_registerComponent(...): Target container is not a DOM element.
But I can see it's present in the DOM
So how do I access this virtual dom div? and load some contents in it?
P.S: I know a way with dangerouslySetInnerHtml but looking for a more better approach
it's just javascript. Yes you can create div. You have to register on some dom element only once to load up all app. You should avoid touching DOM after load of React app, because React does it in very efficient way, but it doesn't mean that it's not possible to touch it. And before loading React app, if you have to check if app container is there, you may do it with such code:
if (!document.getElementById("app")) {
var div = document.createElement("div");
div.id = 'app';
document.body.appendChild(div);
}
ReactDOM.render(<App />, document.getElementById('app'));

jQuery Toggle in SharePoint using XSLT, but all the instances toggle not just the clicked one

I am having a problem with my XSLT, I am using SharePoint 2010 and I am building a custom front-end that will pull data from lists and render the data in a nice manner. I have figured out how to use XSLT with HTML to render a SharePoint list, I wasn't able to add an image of my news feeds because my rep is too low but I will get it up!
Now here is where my problem starts:
I am using jQuery toggle to show/hide the body paragraph of this news feed. The Continue Reading button is where my issue is, every time I click on the "Continue Reading" button in the lower right of each news post, it show/hides all the news items, not just the one I click on.
I have tried using Bootstrap collapse and now I am using jQuery Toggle() however I run into the same issue! Take a look at my XSLT code snippet to display thee body paragraph and the corresponding jQuery code snippet that actives the show/hide toggle:
XSLT:
<tr class="spacer">
<td valign="top" class="td-newscontent">
<div class="news content">
<!-- start excerpt -->
<xsl:value-of select="#BodyExcerpt" disable-output-escaping="yes" />
<div class="moving">
<xsl:value-of select="#Body" disable-output-escaping="yes" />
</div>
<!-- end news excerpt -->
<!-- start continue reading link -->
<xsl:text disable-output-escaping="yes"><![CDATA[<br class="continue-br" />]]></xsl:text>
<a class="butt pull-right continue-right">Continue Reading</a><br /><br />
<!-- end continue reading link -->
</div>
</td>
</tr>
Javascript (jQuery)
$(".moving").hide();
$(".butt").click(function() {
$(".moving").toggle("slow", function() {
});
});
.moving is the actual #body being shown/hidden
.butt is the "continue reading" button (I know butt was a bad name to use)
I have read a few things on the net about "this" but I am not sure how to use it.
First time posting so I couldn't post any images, but when you click on "continue reading" all the body news articles expand then you click it again and all the body news items contract, what I would like it to do is open just the one I am clicking on!
I have a lot going on, everything is housed in SharePoint, using HTML5, Css3, jQuery and XSLT. I started by using IDs but I switched to classes, not sure if that was a good idea but it functions, but not as intended.
Any help would be appreciative, I have been researching this issue for almost 2 weeks so I finally decided to ask some experts :) (Feel free to ask any questions or ask for more information, I will answer with everything I got!)
You are close, so well done for getting this far! Your problem lies in your JavaScript. If you look at the rendered code using your browser's developer tools (F12), you will find that all of the different body texts have the same class (moving) and all of the buttons have the same JavaScript onclick, which is to toggle everything of class .moving.
Thus the solution you are looking for is to match each button with its respective body text. There are two main ways you can do this.
You can give each text div and each button a unique ID by assigning it to some unique feature of the list item (SharePoint list items already have a unique identifier as the field ID). Using xsl:value-of within HTML attributes would violate XML rules, so you can use something called an Attribute Value Template, which is the bit in the curly braces:
<div id="newstext_{#ID}">
<xsl:value-of select="#Body" disable-output-escaping="yes" />
</div>
<!-- etc... -->
<a onclick="$('#newstext_{#ID}').toggle('slow', function() {});">Continue reading</a>
Modify just the JavaScript to target the parent of the button. The following code selects the parent DOM element of the button, which should be the div of class .news, then finds the child of class .moving, then applying your toggle:
$(".butt").click(function() {
$(this).parent().find(".moving").toggle("slow", function() {
});
});
The second method is easier but can get complicated if you end up running a lot of JavaScript. It is easier (and more efficient) to select elements by ID, so personally I think the extra effort is worth it. I haven't tested this code so let me know if it doesn't work. On some of your other points:
no, butt is not a good name for a class - remember, you can use element types in your jQuery selectors, so there is no need to duplicate the type as the class. For example, $('a') selects all the anchor tags on the page.
IDs should be used when elements need to be uniquely identified (e.g. for scripts), classes when you are grouping elements together (e.g. for styles).

jQuery-mobile does not play well with jQuery-tmpl?

Is there any reason why the same template and JavaScript
<script id="taskTemplate" type="text/x-jquery-tmpl">
<li>${name}</li>
</script>
$.getJSON(url, function(data) {
$("#taskTemplate").tmpl(data).appendTo("#tasks");
});
would work as documented with the following jqtouch markup:
<ul class="rounded" id="tasks"></ul>
but result in the template getting rendered outside (after) the unordered list with the following jquery-mobile markup?
<div data-role="content">
<ul data-role="listview" id="tasks"></ul>
</div><!-- /content -->
I realize jquery-mobile is in alpha release, but it has been working nicely so far and I'd prefer not to switch to jqtouch at this stage. Has anyone seen this behavior and found a workaround?
You need to call the refresh method of the listview once your templating is done.
$("yourUl").listview("refresh");
In case .page() method has never been called you may want to do something like this.
try {
$(yourUl).listview("refresh");
} catch(e){
// Well, nothing to do there
}
This has been fixed in alpha 2. See here: http://jquerymobile.com/demos/1.0a2/#docs/lists/docs-lists.html (scroll down to 'Updating lists')
It should look like
$("#taskTemplate").tmpl(data).appendTo("#tasks").page();
you need the .page() at the end.

Using mshtml to set contentEditable, prevent selecting div

My current project involves working with a document editor that, for better or worse, is implemented using mshtml and setting contentEditable to true. We're certainly considering replacing this setup with something else, but for the moment assume it is not an option.
In case it matters, we're doing this using VS 2008 (.Net 3.5) & C#:
document = (HtmlDocument)this.editorWebBrowser.Document;
body = (HtmlBody)document.body;
body.contentEditable = true;
We'd like to hide most of the structural editing behind our UI, but let the user edit the text any way they like. The problem arises when we add a div with any of several styles:
(Adding a body tag to simulate what we're doing programmatically, so you can test in IE, but remember we're working in C#/.Net/VS.)
<BODY contentEditable="true">
<DIV class="intro" style="border: 1px solid blue; width=100%;">
<P>My Intro</P>
</DIV>
<P>Other Text</P>
</BODY>
There are two things wrong with this:
The first click by the user selects the div. We'd like the click to go straight to the text, and never let the user see the resize handles.
If the user places the cursor in Other Text then tries to move to the div text using the keyboard, they're prevented. The div is treated as one character when you are outside of it moving around.
So, effectively, is there any way to make the div behave like just a background decoration, but have everything around it still be editable? This html is completely internal, so we can do anything with it we like. So the div itself doesn't matter. What matters is that we:
Contain several P or other tags
Show the user visually that all the contained P or other tags are part of one group, as styling like border & background color on the current div accomplish now.
This SO question makes me worried that what I want isn't possible with our current setup, but I ask to help anyone else who stumbles on a similar problem. I'll be adding a couple imperfect solutions we've come up with in a moment.
Possible or not, thanks for any thoughts you might have.
Partial solution: Set a containing div to contentEditable=false, then true again on an inner element, like so:
<BODY contentEditable="true">
<DIV class="intro" contentEditable="false" style="border: 1px solid blue; width=100%;">
<P contentEditable="true">My Intro</P>
</DIV>
<P>Other Text</P>
</BODY>
This possibly solves problem 1 (user selecting the div) but does nothing about problem 2.
Since the HTML is internal and doesn't need to play nice with anything else, just represent the area with a table, rather than a div:
<table class="intro">
<tbody>
<tr>
<td>
Intro
</td>
</tr>
</tbody>
</table>
This solves both problems, but significantly complicates the code for editing or parsing. We'd prefer a cleaner solution.