How can I make this Javascript code unobtrusive? - javascript

<div id="detailed">
#foreach (var item in Model.Result.Items)
{
<div id="movie_#(movie.UserMovieID)" class="movie border-gray">
<!-- Some html code -->
</div>
<script type="text/javascript">
new InitMovieWicket(#(MvcHtmlString.Create(movie.ToJSon())),"movie_#(movie.UserMovieID)");
</script>
}
</div>
I am getting list of movie objects from ASP.NET MVC server-side and generating html like above. As you can see , I am also initializing javascript wickets for each of these movies by using movies's JSON data and script tags.
I want to remove these script tags from html and javascript code to be unobtrusive but I dont know how to do that because for each movie to create wicket I need JSON data and without rendering time script tags I cannot see a way to do this. Do you have any idea ? Thanks..
Update
I want want my html code to look like this.
<div id="detailed">
#foreach (var item in Model.Result.Items)
{
<div id="movie_#(movie.UserMovieID)" class="movie border-gray">
<!-- Some html code -->
</div>
}
</div>
And I want my Javascript code to look like this.
$(document).ready(function() {
//init all movie wickets
});

A potentially better way, for users which don't have JavaScript enabled but still want to see movie details for each item, would be to actually render those details as HTML elements, and then hide them if JavaScript is available.
For example, you would render your HTML to look something like:
<div id="detailed">
<div id="movie_#1234" class="movie border-gray">
<div class="wicketData title">Some title</div>
<div class="wicketData year">Year</div>
<div class="wicketData synopsis">Some other stuff</div>
</div>
</div>
And then iterate through the elements and replace divs with anything you like:
$(doument).ready(function() {
// get the parent div
var $detailedParent = $("#detailed");
// get a list of all movie class divs
var $items = $detailedParent.find(".movie");
$.each($items, function(i) {
// get the movie div
var movie = $items[i];
// get all wicket data
var data = movie.find(".wicketData");
// prepare the JSON data using DOM
var movieData = {
title = data.children("title").text(),
year = data.children("year").text(),
synopsis = data.children("synopsis").text()
};
// remove or hide dummy elements
data.remove();
// init your wicket
new InitMovieWicket(movieData, movie.attr('id'));
};
});
This will allow users without JavaScript to get a bit degraded presentation, but all the data will still be there.

here's how I'd do it:
Put only one script tag in the <head></head> part where you initialize an JSON array with all the movies in it (on the server side) like:
var movies = '[{"userMovieID": "123", ...}, {"userMovieID": "432", ...}]';
when the document is ready, you should start building the widgets by first parsing the json array and then iterating through the array of movies, then create a Widget for every movie and insert
<div id="movie_#(movie.UserMovieID)" class="movie border-gray">
<!-- Some html code -->
</div>
to your <div id="detailed">..</div>, maybe you want to use Javascript Templates like jquery-tmpl
The best solution would be if your widget class "InitMovieWicket" creates the <div id="movie_"..>...</div> entry.

Related

How can I make my Ajax feed load multiple WordPress posts based upon a post-id div tag?

I am trying to figure out how to loop my jQuery/Ajax script to load two WordPress posts based off of each WordPress post ID in a div tag, so the Ajax URL loads based upon the ID tags.
You can see my example below. I am using the WordPress News blog as an example of the feed.
https://jsfiddle.net/jdcool279/7L361ru0/17/
I figured out how to load one feed based upon the post-id within the tag, but I can't seem to figure out how to load two feeds via the div tag. To see an example of single feed, please uncomment the script tag within the fiddle. Also, would it be better to change "fetch_comp_content" id tag to a class instead of an id, since I will be needing to include it twice?
Load multiple posts by div post-id:
<div class="col-md-6">
<div class="container">
<div id="fetch_comp_content" post-id="6810"></div>
</div>
</div>
<div class="col-md-6">
<div class="container">
<div id="fetch_comp_content" post-id="6848"></div>
</div>
</div>
Instead of loading 1 post via the script tag:
<script title="true" id="comp_cont_init" post-id="6810"></script>
I would also like to note that the script tag actually loads the script to run the feed. I did not include that in my fiddle, as I wanted to show the JavaScript code.
Any help on this would be much appreciated!
Thank you.
Two quick issues:
You can't repeat Id's in a page, they are unique by definition. use
class instead
You aren't making the requests in the each loop where you have access to specific element instances and the specific post id's from elements
Here's a minimalistic version of what you are trying to accomplish. All I have rendered is the title for the posts.
Note it is better to use data- attributes also
$('.fetch_comp_content').each(function() {
var $el = $(this),
postId = $el.data('post-id'),
urlstring = 'https://wordpress.org/news/wp-json/wp/v2/posts/' + postId;
$.getJSON(urlstring).then(function(data) {
var title = data.title.rendered
$el.append('<h3>' + title + '</h3>');
}).catch(function() {
console.log('Bad request')
})
});
.fetch_comp_content { border:2px solid #ccc; margin:10px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-6">
<div class="container">
<div class="fetch_comp_content" data-post-id="6810"></div>
</div>
</div>
<div class="col-md-6">
<div class="container">
<div class="fetch_comp_content" data-post-id="6846"></div>
</div>
</div>

Fastest way to template and append elements from array

Using jQuery and Javascript, I am building a chatbox from an array of messages. My current setup is something similar to this:
HTML:
<div id="messageTemplate">
<div class="messageContainer">
<div class="chatMessage"></div>
<div class="chatTime"></div>
<div class="chatActions">
<span class="chatAction deleteMessage">Delete</span>
</div>
</div>
</div>
Javascript:
var template=$('#messageTemplate');
var chatbox=$('#chatbox');
$.each(messageArr,function(index,messageObject) {
var newMessage=$(template.html()); //Make a new DOM
newMessage.find('div.chatMessage').text(messageObject.message);
newMessage.find('div.chatTime').text(messageObject.time);
newMessage.find('div.chatAction.deleteMessage').click(function() {
//Delete message Code
});
//Append newMessage to chatbox
newMessage.appendTo(chatbox);
});
This code works, but after reading this article I found out this is not efficient at all. With 100+ chat messages this starts to slow down.
What's the best way to be doing this? Not looking for code to be written for me, but just a general guide on the best method to template, build the html, append, and add click handlers?

Ajax local content place different objects on another page using jQuery

I have a series of products on a page with a class .small-product and inside each one I have an image and its tittle as links to a larger view..
What I want to do it to load the larger view ratings into the .small-product layout. here is the html of the .small-product:
<div class="small-product">
<div class="photo"><img src="image/path>"</div>
<div class="lato" id="rating-stars"></div>
<div class="title">Title</div>
<div class="price">£5</div>
</div>
Large view content to Ajax:
<div class="product-large-reviews" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">
<span itemprop="ratingValue" itemscope itemtype="http://schema.org/ratingValue" class="rating">{module_ratingrank,/images/rating}</span>
<span itemprop="reviewCount" class="counter-ratings"></span>
</div>
My JS with some Jquery:
$('.small-product').each(function() {
var ratingContainer = $('#rating-stars');
var spacing = ('+');
var smallProductLink = $('.small-product a').attr('href'),
sourceRatings = smallProductLink + spacing +'.product-large-reviews';
ratingContainer.load(sourceRatings);
});
Now what I tried and worked but it only works for 1 individual element is if I use a .load('/href/path/to/large/view .product-large-reviews');
But I want every product to use their link to fetch their own information from their large view.
I get only a 404 response from the server saying that it could not be found, I guess it cannot be found because the web address looks like they are together with the class to load e.g www.site.com/path/to/large/view.product-large-reviews. i tried my ways to make a space between but it keeps returning 404.
Some help would be awesomely appreciated!

Formatting dynamically formed HTML elements created after Script is run

So this is actually a very tricky concept to portray so here is my attempt.
I am utilizing an HTML form template in LANDesk Service Desk - tool is irrelevant but important to note that there is back-end code that I cannot touch that is generating HTML.
So basically, the tool is pulling data from a back-end database containing a list of objects. It then inputs this data into an HTML form template that I have created using variables as placeholders for the objects. The HTML is then built on the fly with however many objects are in the database. Thus, I have no way of accessing the head - (which means native JS, and inline CSS).
My template looks like this...
<div class="my-template">
<a class="my-template my-link">My Link</a>
</div>
<script>
var myLinks = document.getElementsByClassName('my-link');
for (var i = 0 ; i < myLinks.length ; i++) {
myLinks[i].style.display = "none";
}
</script>
When I view the source on the loaded page it looks something like this...
<body>
<!--misc. page stuff-->
<!--First Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
<!--Second Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
</body>
All of the elements are formatted the way I want them to be...besides the last element on each page. I have determined that this is because each time the tool is running the object through the template, it is running the script. The issue is, there is a stupid default button that they place at the bottom of each object that is broken. (This is why I have the script changing the style to display: none..should have mentioned this earlier). Basically I want to delay the execution of the script until not only the object has been run through the template...but the entire page has loaded...but I can't seem to get the last button to go away.
I know that this is a lot of poorly written words trying to form an explanation, but I really think this is impossible...but I am convinced there has to be a way. (Also, the company isn't providing us with any help in finding a workaround, so I had to basically MacGyver this one

combine multiple mustache templates, then render HTML

I'd like to integrate multiple mustachejs templates into a larger parent template. I'd like to do this so I have the option to replace one of the children later using just the child template. I'm trying to figure out how best to compile each template, then join them, then replace one of the children. I can build the templates normally using my primitive knowledge of mustache, but I don't know how to "combine" them. Ideally it would be done before any of them was rendered on the page, since the objects which populate them are ajax requests and may come back at different times. I wouldn't want one "module" to show up, then half a second later another module show up. How can I accomplish this. FIDDLE
<!--templates-->
<script type="text/html" id="parent">
<div style="color:blue">
AGE: {{age}}
</div>
</script>
<script type="text/html" id="child1">
<div style="color:green">
AGE: {{age}}}
</div>
</script>
<script type="text/html" id="child2">
<div style="color:gray">
AGE: {{age}}}
</div>
</script>
<script type="text/html" id="replacement">
<div style="color:red">
AGE: {{age}}}
</div>
</script>
//javascript
//info for templates
var parent_obj = {"age":"adult"};
var child1_obj = {"age":"youngest"};
var child2_obj = {"age":"eldest"};
var replacement_child_obj = {"age":"brand new"};
//get templates
var parent_src = $("#parent").html();
var child1_src = $("#child1").html();
var child2_src = $("#child2").html();
var replacement_src = $("#replacement").html();
//make 3 compiled templates
var parent_temp = Handlebars.compile(parent_src);
var child1_temp = Handlebars.compile(child1_src);
var child2_temp = Handlebars.compile(child2_src);
//"somehow" combine first 3 into one template
//render HTML on page
$("body").append(/*rendered template*/);
//wait a bit and then replace child1 with replacement template
var t = setTimeout(function(){
var replacement_temp = Handlebars.compile(replacement_src);
//"somehow" insert into already rended HTML
},1500);
Can you combine the template text prior to compiling them? That seems like the best approach to me. In this way, you can manipulate the template strings, then have one compiled function that you populate when all the data has arrived, adding the resulting element to your document.

Categories

Resources