Getting properties of dojo's dijit.InlineEditBox for ajax request - dojo

In essence I have the same problem as described in this question, but the accepted answer there is not fully working for me.
I want to have the id of the record I'm processing in an HTML5 compliant data-myid attribute, then when the text in the text area is changed, I want call a function that will send an ajax request containing the new value and data-myid to the server. This is important because there can be multiple inlineEditBoxesi a single page. The ajax request part I'm fine with, is getting the proper values to send where I'm stuck.
So far, I know the end result of the HTML declaration will look something like this:
<span data-dojo-type="dijit.InlineEditBox" data-dojo-props="editor:'dijit.form.Textarea'" data-myid="123" title="some title" id="test" >
<script type="dojo/connect" event="onChange" data-dojo-args="myid,value">
console.log(myid + " changed to value " + value);
</script>1339598</span>
But I have not been able to get this to work.

You can get the myId value through
this.domNode.dataset.myid;
... in your onChange event.
Example here : http://jsfiddle.net/psoares/ycEN7/
A more portable solution is to use dojo/dom-attr instead though, like this :
*HTML
<div id="editBox" data-dojo-type="dijit/InlineEditBox"
data-dojo-props="editor:'dijit/form/Textarea'"
data-myid="123"
title="some title">1339598</div>
<div id="output"><div>`
*Javascript :
require(["dojo/dom",
"dojo/dom-attr",
"dojo/parser",
"dojo/html",
"dijit/registry",
"dijit/InlineEditBox",
"dijit/form/Textarea",
"dojo/domReady!"],
function(dom, domAttr, parser, html, registry){
var editBox;
parser.parse().then(function(instances){
editBox = registry.byId("editBox");
editBox.on("change", function(value){
var myId = domAttr.get(this.domNode, "data-myid");
html.set(dom.byId("output"), "Editor " + myId + "'s value changed to " + value);
});
});
});

Related

htmx:afterSettle not working with hx-trigger

This code does not trigger a swap event, even though I can see that the afterSettle event is firing in the console.
<div id="product-gallery" hx-trigger="htmx:afterSettle" hx-get="{% url 'products' %}" hx-swap="outerHTML">
This works, but loops forever of course, with:
<div id="product-gallery" hx-trigger="load" hx-get="{% url 'products' %}" hx-swap="outerHTML">
I can see from htmx.logAll() that the htmx:afterSettle even is firing, it's just not triggering the above element. Have also tried htmx:afterSwap, which is also logged by logAll()
I'm trying to reload the gallery after a form has been swapped out (the form is inside this parent product-gallery div). Which I was hoping I could achieve by adding a from constraint:
<div id="product-gallery" hx-get="{% url 'products' %}" hx-swap="outerHTML" hx-trigger="afterSettle from:.product-form">
Structure is:
<div id="product-gallery">
<div id="product-form-1">
<form>
...
</form>
</div>
...
</div>
Update - it works! Followed solution 3 from https://htmx.org/examples/update-other-content/:
I added a header to my response in the form update view:
if form.is_valid():
form.save()
context = dict()
context['form'] = form
response = render(self.request, 'form_product.html', context)
response['HX-Trigger'] = 'productUpdate'
return response
Then I listen for this event in the gallery div:
<div id="product-gallery" hx-get="{% url 'products' %}" hx-swap="outerHTML" hx-trigger="productUpdate from:body">
The one bit of js I retain is for closing forms when they are valid:
htmx.on("htmx:afterSwap", function(evt) {
const eventIdTarget = evt['target'].id;
if (eventIdTarget === 'product-gallery') {
if ($("[id^=product-form] .alert-warning").length === 0) {
$.magnificPopup.close();
}
}
})
If you have troubles with http redirects, then this might help you:
If you want a response which was triggered via htmx to do a full page reload, then you should not return a http redirect response (302, aka as HttpResponseRedirect in Django).
You need to set the hx-redirect response header: https://htmx.org/reference/#response_headers
If you set hx-redirect and set the http response code to 302, then htmx will do a redirect on ajax-level (not on the full screen).
Next thing which might confuse new users: if you are used to the old post/redirect/get pattern, then there are good news: This is not needed any more.
If the client sends a http-post, and all data validates, you should return a http 2xx response containing the new HTML. There is no need for the outdated redirect/get dance.
If you think the htmx docs could get improved, then you might want to create a pull request to improve the docs.
AFAIK you can't use "afterSettle" like this: hx-trigger="htmx:afterSettle".
If you want to update a second part of the page, then you can use OOB (out-off-band):
The hx-swap-oob attribute allows you to specify that some content in a response should be swapped into the DOM somewhere other than the target, that is "Out of Band". This allows you to piggy back updates to other element updates on a response.
https://htmx.org/attributes/hx-swap-oob/
More about Update other content

How to replace some text with URL in vue?

I want to replace some text from the string with link. I dont know how can I display it. SO far below code displays string with href link.
<span class="text">{{ $t(myText) }}</span>
myText() {
var text = "You can click text.";
var href = "<a href='https://www.google.com'>Click Here</a>";
var replaced = text.replace("click", href);
return replaced;
},
To elaborate on my comment: the handlebars/moustache syntax is used to insert plain text into your template. That means that any string that contains HTML will be inserted as-is without parsing it as DOM.
In order to insert HTML into your template, you will need to use the v-html directive, i.e.:
<span class="text" v-html="$t(myText)"></span>
However, note that this presents a security risk if you're allowing users to insert their own content into the element.

Invalid value for property <position> with two level iframe context

I'm having problem setting marker position and map center, with "Invalid value for property " error or "invalid value for property " error such as:
Error: Invalid value for property : (13.7323691218542,
100.64347976627096) Source File:
http://maps.gstatic.com/intl/en_us/mapfiles/api-3/13/5/main.js Line: 26
This is based on tests on Firefox and Chrome
My top HTML contains:
Javascript function "move_it()"
An iframe (id: "mapIframe") sourced by a cgi (nwfMap.cgi)
And the "mapIframe" iframe cgi contains:
A var mapNwf for a map
A var markerMe for a marker
An iframe (id: "myInfoIframe") sourced by a cgi (nwfSetInfo.cgi)
And the "myInfoIframe" iframe cgi contains:
A call to the function "move_it()" defined in top HTML
This call is intended to move the marker (markerMe) to a specific location
and also to set the map (mapNwf) center to the same specific location
The invocation of the "move_it" was executed OK until when it tried to do:
mrk.setPosition(pos); or
mp.setCenter(pos);
It's here I've encountered the "Invalid value for property ..." errors.
The immediately preceding execution were of:
alert('mp = [' + mp.getCenter() + ']'); and
alert('mrk = [' + mrk.getPosition() + ']');
were OK with correct location (lat/lng) value displayed (map center and marker position)
So the question is, how come getCenter and getPosition worked for same map and marker variables, but the setCenter and setPosition had failed?
If getCenter and getPosition came back with correct data, it indicates that there's no variable context issues, right?
But then how come I can only "read" but not "set" the values via these variables?
Would it be related to the appearance of the google line:
in the top HTML, and in its iframe, and in the iframe's iframe?
Repetition and the nested level causing some google map context issue leading to my problem?
Much thanks in advance for any advice! Followings are relevant code portions for your examination and investigation:
Relevant portions of the top HTML
<html>
........
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"> </script>
<script language="JavaScript">
function move_it(slat, slng) {
var ifrm = document.getElementById('mapIframe');
var mp = ifrm.contentWindow.mapNwf;
var mrk = ifrm.contentWindow.markerMe;
var pos = new google.maps.LatLng(slat,slng);
alert('mp = [' + mp.getCenter() + ']');
alert('mrk = [' + mrk.getPosition() + ']');
alert('pos = [' + pos + ']');
mrk.setPosition(pos);
mp.setCenter(pos);
}
</script>
.........
<div id="nwfMap">
<iframe width=100% height=520 frameBorder=0 src="nwfMap.cgi" name="mapIframe" id="mapIframe" scrolling=no></iframe>
</div>
........
</html>
Relevant portions of the "mapIframe" iframe (produced by nwfMap.cgi)
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var mapNwf = new google.maps.Map(document.getElementById('mapCanvas'), {
zoom: 8,
mapTypeId: google.maps.MapTypeId.HYBRID
});
var latLngPre = new google.maps.LatLng(0.0, 0.0);
var markerMe = new google.maps.Marker({
position: latLngPre,
title: 'Me Here',
map: mapNwf,
draggable: true,
animation: google.maps.Animation.DROP
});
.........
</script>
.........
<div id="myInfoForm" style="display: none;">
<iframe border=1 width=100% height=200 align=center marginwidth=0 marginheight=0 seamless=seamless frameBorder=0 src="nwfSetInfo.cgi" name="myInfoIframe" id="myInfoIframe" scrolling=no></iframe>
</div>
.........
Relevant portions of the "myInfoIframe" iframe (produced by nwfSetInfo.cgi)
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"> </script>
<script type="text/javascript">
parent.parent.move_it(13.7323691218542, 100.643479766271);
</script>
The problem is fixed now, by moving the "move_it()" function definition down from the top level HTML to the mid-level iframe "mapIframe" and by changing the "move_it()" invocation in the "myInfoIframe" iframe from
parent.parent.move_it(13.7323691218542, 100.643479766271);
to
parent.move_it(13.7323691218542, 100.643479766271);
Don't know why, but obviously by the reducing of invocation context level something got corrected on the original "can read but not write on map variable" problem. If any one has a good explanation, would like to hear about it. Thanks.

JavaScript .innerHTMLworking only when called manually

I've got a very simple function, of replacing the innerHTML of a element. I've been trying to debug this for hours but simply can't, and it's infuriating.
When called from a button press the JavaScript (as follows) works well, but when called from another function it doesn't work. I am totally lost as to why this might be, and its a fairly core part of my app
// This loaded function in my actual code is a document listener
// checking for when Cordova is loaded which then calls the loaded function
loaded();
function loaded() {
alert("loaded");
changeText();
}
function changeText() {
alert("started");
document.getElementById('boldStuff').innerHTML = 'Fred Flinstone';
}
Button press and HTML to replace
<div id="main">
<input type='button' onclick='changeText()' value='Change Text'/>
<p>Change this text >> <b id='boldStuff'> THIS TEXT</b> </p>
</div>
It is also here in full on JSFiddle
You are already changed the innerHTML by calling the function loaded(); on onLoad.
Put this in an empty file and same as .html and open with browser and try. I have commented the function loaded();. Now it will be changed in onclick.
<div id="main">
<input type='button' onclick='changeText();' value='Change Text'/>
<p>Change this text >> <b id='boldStuff'> THIS TEXT</b> </p>
</div>
<script>
//loaded();
function loaded() {
alert("loaded");
changeText();
}
function changeText() {
alert("started");
document.getElementById('boldStuff').innerHTML = 'Fred Flinstone';
}
</script>
The problem here is, that the element you're trying to manipulate is not yet existing when you are calling the changeText() function.
To ensure that the code is only executed after the page has finished loading (and all elements are in place) you can use the onload handler on the body element like this:
<body onload="loaded();">
Additionally you should know, that it's very bad practice to manipulate values by using the innerHTML property. The correct way is to use DOM Manipulations, maybe this can help you.
You script loads before the element (boldStuff) is loaded,
Test Link - 1 - Put the js in a seperate file
Test Link - 2 - put the js at the very end, before closing the <body>

Access Elements of a DOJO DIV

I have two Hyper Links on to a DOJO DIv
var create = dojo.create("div",{
id:"create_links",
className:"iconRow1",
innerHTML:"<a class='popupLink' href='javascript:openCreateDialog()'>Create </a> <span>|</span><a href='javascript:openUploadDialog()'>Batch </a>"
},dojo.query(".ui-jqgrid-titlebar")[0]);
On click of the Batch Hyperlink , i have a function
function openUploadDialog()
{
// Here i want to disable the Create Hyper Link tried this way
dojo.byId('create_links')[1].disabled=true; // Not working
}
See whether i can answer your question.
HTML Part:
<div id="create_links">
g
h
</div>
JS Part:
dojo.addOnLoad(function() {
var a = dojo.query("#create_links a")[1];
dojo.connect(a,'click',function(e){
console.log(e.preventDefault())
})
})
#Kiran, you are treating the return of dojo.byId('create_links') like an array when that statement will return to you a node on the dom.
Also, hyperlinks don't support a disabled attribute to prevent them from being actionable. You could probably create a click handler that returns false to accomplish this type of functionality, or like #rajkamal mentioned, calling e.preventDefault(). #rajkamal also provides a good solution to selection the link properly.