I have a custom jquery plugin that use to create drop down html for a search box.
Inside that, html is created as follows.
$.each(stack, function (i, stackItem) {
var url = _getItemURL(stackItem, lang);
if (stackItem.INS !== undefined) {
html += '<li class="row"> ' + stackItem.DS_HIGHLIGHTED + ' - ' + stackItem.E + '<br>' + stackItem.TICKER_DESC + ' </li>';
} else {
html += '<li class="row"> ' + stackItem.COMPANY_DESC_HIGHLIGHTED + '<br>' /*+ _getCountry(stackItem.CC, lang)*/ + ' </li>';
}
itemCount++;
});
As you can see href attribute is used to create links in this html. But when user click on those links application reloads the browser page. I want it to correctly map to different route in the application like in hbs files as follows
<li> {{#link-to 'stock-overview' 'en' 'tdwl' '1010'}}Stock{{/link-to}} </li>
How can I generate html like that inside previous java script code.
Appreciate any help?
First, I would recommend you to think if you really need that jQuery plugin or could go with a plain ember solution. There are some pretty fancy addons like ember-power-select.
But if you really want to do that you need to understand that a {{#link-to}} does not only generate a <a> tag but only handles clicks on it and then doing a transitionTo.
So no, its not possible to do this when you simply append the HTML to the DOM. You would have to catch the click events on the <a> tags manually and then trigger the transition. It depends a bit how you inject the html into the DOM.
One thing you could do is to create a unique id for each <a> tag and after you inserted the html into the DOM you find the <a> tags by the id and attach the onclick event.
A better way would be to create DOM instead of HTML, so manually call document.createElement and then attach the click event.
To trigger the transition you can do something like this inside any Object that has the owner injected (like a component):
Ember.getOwner(this).lookup('controller:application').transitionToRoute('stock-overview', 'en', 'tdwl', '1010');
However cleanly the best solution would be to go for a ember handlebars template and a {{#each}} loop instead of the jQuery solution. To tell you how to do that however we need more information. So best is probably you ask a new question and explain exactly what you want to achieve, and now ask about a problem you have with a probably wrong solution for another problem.
Related
I am using Bootstrap Vue and would like to use a formatter callback to insert html into a column inside the table. The Bootstrap documentation example formats the link as an anchor link
Ex. https://bootstrap-vue.js.org/docs/components/table/#shirley-partridge
<b-table striped responsive hover :items="episodes" :fields="fields">
<template v-slot:cell(version)="data">
<a :href="`${data.value.replace(/[^a-z]+/i,'-').toLowerCase()}`">{{ data.value }}</a>
</template>
</b-table>
I am pulling in a full url from the version property and would like to only use this url in the template, how can I remove everything before my url using the formatter?
this.episodes = response.map((item) => {
return {
category: item.fields.title,
episode_name: item.fields.splash,
episode_acronym: item.fields.description,
version: 'https://myurl/webinars' + item.fields.slug + '/' +'test',
}
})
Desired link would be https://myurl/webinars....
I was able to get this working, by keeping the relative url format, and updating the formatter with a - instead of a + sign
<a :href="`${data.value.replace(/[^a-z]-/i,'-').toLowerCase()}`">Definition</a>
This Ember template code...
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{rental.bedrooms}}
</div>
<div class="detail temperature">
<span>Current Temperature:</span> {{city-temperature location=rental.city}}
</div>
...results in this rendering...
How could one get the "25C" text to render on the same line as "Current Temperature" in the same way that "San Francisco" is on the same line as "Location"?
I have tried getting the city-temperature component to return only text, but (secondary question here) is it even possible for a component to return only text if the text is from a remote ajax request since the promise seems to need a DOM element to append to?
This Ember app is available here on GitHub. It's a modified version of the official Ember.js tutorial app with this "Current Temperature" detail added.
The problem is that; city-temperature is a component; and by default ember components is assigned div as their tags. Due to this; the content of city-temperature starts at a new line.
What can you do? Play with css and make sure div tag of city-temperature does not start at a new line; but instead floating right within the owner div. The second option is making city-temperature component tagless; so that it does not start at a new line. To achieve that; you can just declare:
tagName: ''
within city-temperature.js. You can see the following twiddle to see the second option I mentioned.
After reading your comments; I have forked your repository and made minor modifications to achieve what you want. You can check my repository and my corresponding commit to see what I changed.
Basically; I really did not like the idea that weather service is returning a DOM element. I have changed it to return an instance of ember promise (I mean Ember.RSVP.Promise). Within city-temperature.js I just set a retrieved weather value from weather service and set it to the component instead of making DOM modification. Finally; I modified city-temperature.hbs to render weatherValue and added a simple css item in order to prevent weather-container div to insert a new line break.
I am not sure; whether you will like my solution or not; but I guess you will retrieve the visual appearance you want. You can always rely on promises for async tasks; you do not need to create DOM elements and pass them around to components and append them to somewhere within DOM tree of the corresponding component. I believe one of the reasons we are making use of a framework like Ember is to prevent such DOM modifications. Best regards.
An ember component adds a div by default. If you don't want to add this div tag, you need to set tagName to an empty string.
That's called tagless component.
Further, for your case, you can give a tagName='span' so you will not need a span in your template.
export default Ember.Component.extend({
tagName: 'span',
classNames: ['weather-container'],
weather: Ember.inject.service(),
//rest of your code...
});
I found a similar question here: Wrap URL within a string with a href tags using Coldfusion
But what I want to do is replace tags with a slightly modified version AFTER the user has submitted it to the server. So here is some typical HTML text that the user will submit to the server:
<p>Terminator Genisys is an upcoming 2015 American science fiction action film directed by Alan Taylor. You can find out more by clicking here</p>
What I want to do is replace the <a href=""> part with a new version which would be like this:
...
clicking here
So I'm just adding the text rel="nofollow noreferrer" to the tag.
I must match anchor tags that contain a href attribute with a URL, not just the URL string itself, because sometimes a user could just do this:
<p>Terminator Genisys is an upcoming 2015 American science fiction action film directed by Alan Taylor. You can find out more by http://www.imdb.com</p>
In which case I still only want to replace the tag. I don't want to touch the actual anchor text used even though it is a URL.
So how could I rewrite this Regex
#REReplaceNoCase(myStr, "(\bhttp://[a-z0-9\.\-_:~###%&/?+=]+)", "\1", "all")#
the other way round, where its selecting tags and replacing them with my modified text?
If you're willing, this is a really easy task for jQuery (client-side)
JSFiddle: http://jsfiddle.net/mz1rwo0u/
$(document).ready(function () {
$("a").each(function(e) {
if ($(this).attr('href').match(/^https?:\/\/(www\.)?imdb\.com/i)) {
$(this).attr('rel','nofollow noreferrer');
}});
});
(If you right click any of the imdb links and Inspect Element, you'll see the rel attribute is added to the imdb links. Note that View Source won't reflect the changes, but Inspect Element is the important part.)
If you want to effect every a link, you can do this.
$(document).ready(function () {
$("a").each(function(e) {
$(this).attr('rel','nofollow noreferrer');
});
});
Finally, you can also use a selector to narrow it down, you might have the content loading into a dom element with the id contentSection. You can do...
$(document).ready(function () {
$("#contentSection a").each(function(e) {
if ($(this).attr('href').match(/^https?:\/\/(www\.)?imdb\.com/i)) {
$(this).attr('rel','nofollow noreferrer');
}});
});
It's a bit tougher to reliably parse this in cold fusion without the possibility of accidentally adding it twice (without invoking a tool like jSoup) but the jQuery version is client-side and works by obtaining data from the DOM rather than trying to hot-wire into it (a jSoup implementation works similarly, creating a DOM-like structure you can work with).
When talking about client-side vs server-side, you have to consider the mythical user who doesn't have javascript enabled (or who turns it off with malicious intent). If this functionality is not mission-critical. I'd use JQuery to do it. I've used similar functionality to pop an alert box when the user clicks an outside link on one of my sites.
Here's a jSoup implementation, quick and dirty. jSoup is great for how it selects similarly to jQuery.
<cfscript>
jsoup = CreateObject("java", "org.jsoup.Jsoup");
HTMLDocument = jsoup.parse("<A href='http://imdb.com'>test</a> - <A href='http://google.com'>google</a>");
As = htmldocument.select("a");
for (link in As) {
if (reFindnoCase("^https?:\/\/(www\.)?imdb\.com",link.attr("href"))) {
link.attr("rel","nofollow noreferrer");
}
}
writeOutput(htmldocument);
</cfscript>
I am trying to use ember to show a dynamic list of found content. The problem is that when I try to put handlebars in html attributes, everything breaks.
RegApp.PatronsFound = Ember.CollectionView.create
tagName: 'table'
content: []
itemViewClass: Ember.View.extend
template: Ember.Handlebars.compile("<td><button onclick='alert({{content.id}})'>{{content.name}}</button>")
RegApp.PatronsFound.appendTo('body')
When it is fed a piece of content with the ID of 3 and the name FOO, I want this html to be generated:
<button onclick="alert(3)">FOO</button>
Instead, I get this:
<button onclick="alert(<script id=" metamorph-4-start'="" type="text/x-placeholder">3<script id="metamorph-4-end" type="text/x-placeholder"></script>)'>FOO</button>
You can use
{{unbound content.id}}
to arbitrarily insert values into your templates. Normally, such values are wrapped in metamorph tags which allow the displayed value to be bound to the backing value, and updated whenever the backing value changes. This only works if the output is regular HTML, not, in this case, spanning event handlers and embedded JS. {{unbound}} inserts the value at that property path once, without metamorph tags, and without being updated if that value changes in the future.
Here is the scenario... I have a a checkbox next to each field that I am replacing on page load with jquery with "Delete" text that enables me to delete the field via jquery, which is working fine. Like so...
$(".profile-status-box").each(function(){ $(this).replaceWith('<span class="delete">' + 'Delete' + '</span>') });
The problem comes in however is that after page load, I am also giving the user the option to dynamically add new fields. The new added fields though have the checkbox and not the delete link because they are not being replaced by jquery since they are being added after the initial page load.
Is't possible to replace the content of new elements added to the page without doing a page refresh? If not, I can always have two templates with different markup depending one for js and one for non js, but I was trying to avoind taht.
Thanks in advance.
You can use the .livequery() plugin, like this:
$(".profile-status-box").livequery(function(){
$(this).replaceWith('<span class="delete">Delete</span>')
});
The anonymous function is run against every element found, and each new element matching the selector as they're added.
Have a look at this kool demo. It removes and adds elements like a charm.
http://www.dustindiaz.com/basement/addRemoveChild.html
Here's how:
First of all, the (x)html is real simple.
xHTML Snippet
<input type="hidden" value="0" id="theValue" />
<p>Add Some Elements</p>
<div id="myDiv"> </div>
The hidden input element simply gives you a chance to dynamically call a number you could start with. This, for instance could be set with PHP or ASP. The onclick event handler is used to call the function. Lastly, the div element is set and ready to receive some children appended unto itself (gosh that sounds wierd).
Mkay, so far so easy. Now the JS functions.
addElement JavaScript Function
function addElement() {
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value -1)+ 2;
numi.value = num;
var newdiv = document.createElement('div');
var divIdName = 'my'+num+'Div';
newdiv.setAttribute('id',divIdName);
newdiv.innerHTML = 'Element Number '+num+' has been added! <a href=\'#\' onclick=\'removeElement('+divIdName+')\'>Remove the div "'+divIdName+'"</a>';
ni.appendChild(newdiv);
}
And if you want to,
removeElement JavaScript Function
function removeElement(divNum) {
var d = document.getElementById('myDiv');
var olddiv = document.getElementById(divNum);
d.removeChild(olddiv);
}
and thats that. bobs your uncle.
This is taken from this article/tutorial: http://www.dustindiaz.com/add-and-remove-html-elements-dynamically-with-javascript/
I've just learnt this myself. thank you for the question
Hope that helps.
PK