Manipulate DOM Element that raises an event - javascript

If I have this code:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i.id)'>link</a>
</li>
and this JS:
function doSomething(objId) {
$.ajax({ url: 'myUrl.php', success: successHandler});
}
function successHandler(response) {
// do something with the response
}
The user clicks on the link, which changes class, an AJAX request is made, then a success handler is called (I've omitted the error handler for brevity).
I need some clean way to access the <li> element whose child originated the click event in both functions:
in doSomething() (for example to write "loading..." and add a "loading" CSS class, maybe with ng-class)
in successHandler() (if success, remove "loading..." and remove the class)
What is the best way to achieve this? I've tried:
using data- attributes (I cannot manipulate them in Angular and don't solve the problem)
using global variables (whoa, bad)
using scope variables, like $scope.currentClickedItem

I recommend not to access dom element directly. Best way to do achieve your goal in angular is:
html:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i)' ng-class="{active: i.isActive}">link</a>
</li>
js:
function doSomething(obj) {
$.ajax({ url: 'myUrl.php', success: successHandler.bind(this, obj});
}
function successHandler(obj, response) {
// do anything with the response and object
obj.isActive = true;
}
But anyhow, you want to access dom:
You can use angular $event object to access clicked element. if you need to access <li>, element.parentElement is your friend.
html:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i.id, $event)'>link</a>
</li>
js:
function doSomething(objId, $event) {
var element = $event.target;
$.ajax({ url: 'myUrl.php', success: successHandler.bind(this, element});
}
function successHandler(element, response) {
// do anything with the response and element
}
bind method's first argument can be null instead of this if they do not need to share same scope.

You can manipulate the object rather than the element.
<li ng-repeat='i in items'>
<a ng-class="i.loading ? 'loading' : ''" ng-click='doSomething(i)'>link</a>
</li>
JS
function doSomething(obj) {
obj.loading = true;
var objId = obj.id;
$.ajax({ url: 'myUrl.php', success: successHandler});
}
function successHandler(response) {
// do something with the response
}

I will answer my own question but leaving #CKK's one as "answered".
There's no need to manipulate the element in doSomething() because I can do:
<li ng-class='i.class' ng-repeat='i in items'>
{{ i.message }}
<a ng-click='doSomething(i)'>...</a>
</li>
Javascript:
function doSomething(obj)
{
obj.class='loading-class';
obj.message="Loading...";
// ajax call...
}

Related

How to pass variable to child function from HTML page

I want to pass a value from HTML page to child function from parent function.
HTML Page:
<div class="bottom_wrapper clearfix">
<div class="message_input_wrapper">
<input class="message_input" placeholder="Type your message here..." />
</div>
<div class="send_message">
<div class="icon"></div>
<div class="text">Send/div>
</div>
</div>
Parent Function Call:
$('.send_message').click(function (e) {
return [sendMessage(getMessageText()),sendMessage1(getMessageText1())];
});
$('.message_input').keyup(function (e) {
if (e.which === 13) {
return [sendMessage(getMessageText()),sendMessage1(getMessageText1())];
}
});
here getMessageText1 is child function.
Child Function:
getMessageText1 = function () {
var result="";
var id = Parent_FUNC_INPUT;
$.ajax({
url:"func.php",
type: 'POST',
data: ({id:id}),
async: false,
success:function(data) {
result = data;
}
});
I want to populate [[id]] variable in child function from parent function.
First, I'll do my best to clean up the HTML:
<div class="bottom_wrapper clearfix">
<div class="message_input_wrapper">
<input class="message_input" placeholder="Type your message here..." />
</div>
<div class="send_message">
<div class="icon"></div>
</div>
<div class="text">Send</div>
</div>
Using proper indentation will make things far easier to read. And while we're on the subject, you may want to use dashes - instead of underscores _ in your class names, as that's the common convention.
On to your question, it seems like what you want to do is simply pass an argument to getMessageText1 from within (as you refer to it) a "parent" function bound to an event listener.
So you'd define this "child" function with a single parameter:
function getMessageText1(Parent_FUNC_INPUT) {
...
var id = Parent_FUNC_INPUT;
...
}
And then you can just call it with getMessageText1(value) where value is whatever you want to pass in.
One more note: for readability's sake I recommend you do not name your functions the way you have. Having two functions getMessageText and getMessageText1 will just be a source of confusion later on. Instead, think of something more descriptive, ala getMessageTextFromID.
Hopefully I answered the question you meant to ask. Let me know.

Ajax call inside class attribute

I'm moving a php / js / ajax script to wordpress
I encountered something that i've never seen before, I understand what it does, but i'm trying to figure out how to make this work for wordpress.
the code:
<a id="a" class="tab block sel {content:'cont_1', ajaxContent:'php/templates.php',ajaxData:'type=pistols'}">Pistols</a>
<a id="b" class="tab block {content:'cont_2', ajaxContent:'php/templates.php',ajaxData:'type=rifles'}">Rifles</a>
<a id="c" class="tab block {content:'cont_3', ajaxContent:'php/templates.php',ajaxData:'type=shotguns'}">Shotguns</a>
<a id="d" class="tab block {content:'cont_4', ajaxContent:'php/templates.php',ajaxData:'type=cameras'}" >Cameras</a>
<a id="e" class="tab block {content:'cont_4', ajaxContent:'php/templates.php',ajaxData:'type=audios'}" >Audio</a>
Templates PHP:
if(isset($_POST['type'])) {
//The div for the manufacturer tabs, uniquely identified by the $_POST['type']
echo "<ul id=\"".$_POST['type']."\" class=\"shadetabs\" style=\"position:relative; top:-12px; width:905px;\">";
if ($_POST['type'] === 'pistols') {
$manufacturers = .. and so on
From what i can understand, we are calling Templates.php and passing $_POST['type']. When this is compoleted, the script replaces the content of a <div id="cont_1"
in wordpress, i can't call random php files, since ajax will not work. I need to turn this into a function and hook it to wordpress.
Does anyone know how this type of code works?
As alternative, I'm planning to do the following, but I would prefer to keep it similar to the original code and this will need lots of extra lines of code.
var tab = jQuery("#a").type;
jQuery.ajax({
url: custom_designer.ajax_url,
type: 'post',
data: {
action: 'php_template_function'
type: tab
},
success: function (response) {
document.getElementById('caseclub_response').innerHTML = response;
document.getElementById("buy_case_foam_added").submit();
}
});
Does anyone know how this type of code works?
It looks like there is some JavaScript that extracts the object string from the class attribute, then fetches the HTML from template.php and writes it somewhere.
For example:
function fetchList(element) {
var settings = element.className.match(/\{.+\}/);
settings = eval('(' + settings[0] + ')') // eww
fetch(settings.ajaxContent, {
method: 'post',
body: settings.ajaxData
}).then((response) => {
// Error handling...
response.text().then(() => {
// Now writes the HTML somewhere...
});
});
}
If you want to copy what they did, see if you can find the original code using the Inspector.

Isit possible to pass value into <div data-value="" > by jquery?

This is my html code
<div data-percent="" ></div>
This is my javascript
function retrieveProgressbar(){
$.ajax({
type:"post",
url:"retrieveprogressbar.php",
data:"progressbar",
success:function(data){
$(this).data("percent").html(data);
}
});
}
retrieveProgressbar();
I need the value retrieved by ajax to be displayed in the data-percent="". I am not sure how to do that. I have another javascript that needs to use this value to execute.
Need to use .attr() method.
<div data-percent="" id="datadiv"></div>
<script>
function retrieveProgressbar() {
$.ajax({
type: "post",
url: "retrieveprogressbar.php",
data: "progressbar",
success: function (data) {
//$("#datadiv").attr("data-percent", data);
// OR
$(this).attr("data-percent", data);
}
});
}
retrieveProgressbar();
</script>
HTML:
<div data-percent=""></div>
The proper way to assign data on jquery is
var new_data_value = "I will be the new value.";
$("div").data("percent",new_data_value);
The .data() method allows us to attach data of any type to DOM elements in a way that is safe from circular references and therefore from memory leaks.
You can retrieve the data by:
var value = $( "div" ).data( "percent" );
.attr() on the other hand set/get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.
It does not attach data of any type to DOM elements.
$("div").attr("data-percent",data_value);
Sources:
https://api.jquery.com/data/
http://api.jquery.com/attr/
Yep, you can use the .attr( function instead.
$(this).attr("data-percent", your_value);

Vue JS - Putting Json on data

I want to put my JSON data into Vue data, and a display, why can't I get to work?
compiled: function(){
var self = this;
console.log('teste');
$.ajax({
url: 'js/fake-ws.json',
complete: function (data) {
self.$data.musics = data;
console.log(self.$data.musics);
}
})
}
<div id="playlist" class="panel panel-default">
<div class="panel-body">
<ul>
<li v-repeat="musics.item" >
{{nome}}
</li>
<ul>
<div>
</div>
I can't get the code to work.. why?
I think the problem is that musics is not initially part of your Vue data, so when you set its value using self.$data.musics = data, Vue doesn't know it needs to watch it. Instead you need to use the $add method like this:
self.$set("musics", data);
From the VueJs Guide:
In ECMAScript 5 there is no way to detect when a new property is added to an Object, or when a property is deleted from an Object. To deal with that, observed objects will be augmented with two methods: $add(key, value) and $delete(key). These methods can be used to add / delete properties from observed objects while triggering the desired View updates.
this refers to the whole Vue object, so musics object is already accessible via this.musics. More info here in the VueJS API reference and here in the VueJS guide, and more on this here.
With that in mind the code should look something like this:
var playlist = new Vue({
el: '#playlist',
data:{
musics: '',
}
methods: {
compiled: function(){
var self = this;
console.log('test');
$.ajax({
url: 'js/fake-ws.json',
complete: function (data) {
self.musics = data
console.log(self.musics);
}
})
}
}
And the view would be something like this:
<div id="playlist" class="panel panel-default">
<div class="panel-body">
<ul>
<li v-repeat="musics">
{{nome}}
</li>
<ul>
</div>
</div>
Also look at the code of this example.
you can do that with vue-resource. Include vue-resource.js into your app or html file and:
{
// GET /someUrl
this.$http.get('/someUrl').then(response => {
// get body data
this.someData = response.body;
}, response => {
// error callback
});
}

Passing parameters to on click jquery event from dynamic list of anchor tags

I'm working on a list of elements in my asp.net mvc project. Each element is part of a ul, and the list elements are generated based on a list in my model.
I'm trying to add a delete button to each of these elements, but I'm struggelig a bit with how to make these elements unique, for jquery to pass the correct parameters to my action later on.
Each element has its own guid, but I can't figure out how to pass these along to the .on('click') jquery handler.
Here's the relevant part of my razor view:
<ul class="panel-tasks ui-sortable">
#foreach (RunModel run in Model.PlannedRuns)
{
<li>
<label>
<i class="fa fa-edit"></i>
<!--<i class="fa fa-ellipsis-v icon-dragtask"></i>-->
<span class="task-description">#run.Name</span>
<span class="sl-task-details">#run.RunTask</span>
<span class="sl-task-unit">#run.ConveyanceId</span>
<span class="sl-task-location">#run.Operation.WellContract.Location, #run.Operation.WellContract.Name</span>
</label>
<div class="options">
</i>
</div>
</li>
}
</ul>
And here's my javascript:
<script type="text/javascript">
$("#del").on("click", function (runId) {
$.ajax({
url: "#Url.Action("DeleteRun", "Planning")",
type: "GET",
dataType: "json",
data: { runId: runId },
error: function (msg) {
// Error handling
},
success: function (msg) {
// Success handling
}
});
});
</script>
I do realize I could add onClick to the anchor tag passing along the id as a parameter there, but I was hoping using jquery would do the trick, like mentioned above. Also, is there a recommended approach for doing tasks like this when several html elements use the same method?
You can use a data-* parameter on the delete button specific to that instance which you can then retrieve on click. You also need to make the delete button use a class attribute, otherwise they will be duplicated in the loop. Try this:
<div class="options">
<i class="fa fa-trash-o"></i>
</div>
$(".del").on("click", function (e) {
e.preventDefault();
var runid = $(this).data('runid');
$.ajax({
url: "#Url.Action("DeleteRun", "Planning")",
type: "GET",
dataType: "json",
data: { runId: runId },
error: function (msg) {
// Error handling
},
success: function (msg) {
// Success handling
}
});
});
The answers using data- attributes are elegant and do the job. However, I would like to propose a (slightly) different approach:
#foreach (RunModel run in Model.PlannedRuns)
{
<li id="#run.Id">
...........
</li>
}
Inside the a elements, set your del id as class.
$(".del").on("click", function () {
var runid = $(this).parent().id;
//..............
});
The advantages of this solution:
Your li elements have an id which can be used by other JavaScript functions as well
No need to play around with attributes (be careful as Firefox is very picky with data- attributes)
Additionally, your delete a elements won't have duplicate ids.
You can access the item clicked with $(this) in a click event (and most events).
$(".del").on("click", function () {
var runId = $(this).data("runId");
$.ajax({
url: "#Url.Action("DeleteRun", "Planning")",
type: "GET",
dataType: "json",
data: { runId: runId },
error: function (msg) {
// Error handling
},
success: function (msg) {
// Success handling
}
});
});
and insert the id as data-runId= in the HTML:
<i class="fa fa-trash-o"></i>
As the delete button is a boookmark only (#) the only effect it may have is to move the page to the top. To stop that add an event parameter and call preventdefault() on it. (or simply return false from the event handler).
$(".del").on("click", function (e) {
e.preventDefault();
And as Rory McCrossan points out, you should not have duplicate ids on your delete buttons (use a class). Dupe ids will actually work on most browsers, but are considered a bad thing :)

Categories