Once a kendo widget is destroyed, it and its HTML is no longer needed in the page. The framwork cleans all HTML outside the widget but not inside widget. So I need to write few lines of code to remove the HTML in main widget every time I destroy a widget.
How can I avoid this boilerplate code to remove HTML in the main widget's element? Why does not kendo clean HTML inside main Widget?
Kendo widget's destroy() method is just preparing widget to remove from the site. Assume that you want do remove a big container contains one or few widgets. Removing all widget's html separately using destroy() method and then remove container will cause decline in performance.
I don't know where you see few lines of code to destroy and remove widget - it's just two:
$("#widget").data("yourWidget").destory();
$("#widget").remove();
And, you can easly create your own global function to destroy and remove widget:
function deleteWidget(kendoWidget){
var element = kendoWidget.element;
kendoWidget.destroy();
element.remove();
}
If you want to recreate widget you can use:
function emptyWidget(kendoWidget){
var element = kendoWidget.element;
kendoWidget.destroy();
element.empty();
}
And then you can then use your empty html elemnt to create new widget.
More about destroy widgets in official kendo documentation: http://docs.telerik.com/kendo-ui/framework/widgets/destroy.
Related
I have a component A that should dynamically change the font size of some of it's contents. I currently use CSS variables to do that and the component will contribute some CSS String containing these CSS variables:
public void renderHead(IHeaderResponse response) {
String fontCss = // dynamically fetch CSS cariables
response.render(CssHeaderItem.forCSS(fontCss, "font-css"));
}
On the same page I have the possibility to change these font sizes using an AJAX update within another component B. This will add the component A to the AjaxRequestTarget, which will cause the renderHead method to be executed with updated values for the font CSS variables.
However, I don't see an updated font size in my browser as the old CSS variables still seem to be present. How can I enforce the new CSS to overwrite the old one?
So far I found 2 solutions, that seem like dirty workarounds to me:
Add the whole page to the AjaxRequestTarget, so the whole page will be refreshed.
Add JavaScript to the AJAX update to remove the old styling with:
var allStyles = document.getElementsByTagName("style");
for (var style of allStyles) {
if (style.getAttribute("id").includes("font-css")) {
style.remove();
}
}
Is there a cleaner solution to this problem?
You found the problem with workaround 2.
response.render(CssHeaderItem.forCSS(fontCss, "font-css"));
adds <style id="font-css"> ... </style> to the page. Later when the Ajax response contributes the new content the JavaScript logic finds that there is an HTML element with id font-css and assumes that there is nothing to do.
A simple solution is to use dynamic id, e.g. by using UUID in #renderHead().
Another solution is to make this <style> a proper Wicket Component, a Label, that could be added to the AjaxRequestTarget with an updated Model when needed.
I am trying to use jquery plugin inside template:
But I am getting error, can anyone point me out where it goes wrong?
I've called the function $("span.pie").peity("pie") inside the script tag and tried to use it inside one of my column template of the grid. { field: 'userId', title: 'ID', template:"<span class=ul>#=userId#</span> </br> <span class='pie'>1/5</span>", width:60 }
https://dojo.telerik.com/ihEzi
The problem is that you call the plugin before the template has been rendered. The call to the plugin only finds and affects what is in the DOM at that time. Anything you add afterwards, even though it matches the span.pie selector, is unaffected until you call it again.
I suggest subscribing to the grid dataBound event (see the Telerik documentation) and calling the plugin in the handler function you define. DataBound is called after the grid has rendered all its UI components so everything is then in the DOM ready to be found.
I am not sure if I am adding my JS assets correctly and would like some advice if I am not.
In octoberCMS I have created a custom formWidget that uses the Google Maps API.
I am using my formWidget inside a child form that is rendered via AJaX as a modal when required.
If I use the following code in my widget class:
public function loadAssets(){
$this->addJs("http://maps.googleapis.com/maps/api/js?key=myappkeyhere&libraries=places");
$this->addJs('js/geocomplete/jquery.geocomplete.min.js');
$this->addJs('js/addressinput.js');
$this->addCss('css/addressinput.css');
}
The JS loads with the Page load and not when the widget is rendered. This produces these issues:
The google-maps API returns an error saying it has been loaded multiple times.
Events tied to DOM elements in the child fail since the elements are not in the DOM until the form is called.
The workaround I am using is to embed my JS into the formWidget partial.
Is there a way to make the addJS method work for the formWidget when it is part of a child form?
After some investigation, I realised that my formWidget using the addJs() method would make the widget JS available globally to the entire page even before the formWidget existed or was even needed.
While I could have created an elaborate, fancy JS involving listeners for DOM insertions and blah blah blah, this was not ideal (mainly because the widget properties change based on implementation).
The quickest/safest way to include JS that is tightly bound to a complex formWidget is to include it in the partial. This ensures the form widget will work properly both in a standalone form and in situations where the widget is part of child form that is created via an Ajax load.
(If you know of a better way please let me know)
I have javascript files defined in the <head> of both my layout decorator template and my individual pages which are decorated. When I update a thymeleaf fragment in one of my pages the javascript defined in the head of the parent page no longer works. Is there a standard way to 'refresh' these js files?
Thanks.
Additional clarification :
I have a form submitted by an ajax call which updates a table in the page. I have a Jquery onClick function targeting a button in the updated table. The javascript doesn't seem able to bind to the returned elements in the updated part of the page. I select by element class and can see that the selection works prior to the partial fragment render.
For me it is unclear what you mean by
javascript defined in the head of the parent page no longer works.
The page is created on the server. Normally it contains urls of the javascript files
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
In this case 'refreshing' the javascript files can happen only in the client.
Check the html of the page in the client.
Are the tags as expected ?
Are there tags for all expected javascript files ?
With the browser tools (for example Google Chrom developer tools ) check that all script files are actually loaded.
If this doesnt help, it could be that the order of the script tags has changed between the first and second load. This could cause a different behaviour of the javascript executed in the browser.
EDIT :
With the initial load you bind javascript callbacks to dom elements.
You do this directly or through Jquery or other libraries.
When a new dom element is loaded, it has no callbacks bound to it, even if it has the same id as a replaced dom element.
So after the load you have to bind your callbacks again.
If you bound them 'by hand', just bind it again.
If you are using a JQuery plugin, that made the bindings, look into the code or documentation, many of them have a function for that or you can call initialization again.
Once you added new content to the DOM you need to bind again the new content.
Let's say I have a button with some class, the event in binded to the class:
<button class="someclass">Button 1</button>
<script>
var something = function() {
// do something
};
$(".someclass").on("click", something);
</script>
If I add more buttons from the same class to the DOM, they will have not have the click event binded. So once you load the new content via ajax, also remove all binding and add again (you need to remove or you will have buttons with 2 events).
$(".someclass").off("click");
$(".someclass").on("click" , something);
I have a task to change envelope icons on the main Activities view page (Work Place, My Work -> Activities) for every row in the grid, depending on the custom status of the row in crm 4.0. I need to do it using JavaScript. Does anybody know if there is a way to do that and where should the JavaScript code be placed? I am assuming that I need to intercept grid onLoad event, go through the grid, check the condition and flip the url of the icon. But I cannot figure out how to hook into that event...
Thanks very much!
I got several very useful advices and here is what I got so far.
1. I added SiteMap to load a custom page, instead of default one (/workplace/home_activities.aspx)
2. Here is the code of the custom page, placing onreadystatechange in the html was the only way I could get this function to run. Do not know why.
HTML>
HEAD>
TITLE>
script language="javascript" type="text/javascript">
function Run()
{
var objIframe = getIframe();
if(objIframe.readyState == "complete")
{
var docFrame = objIframe.contentWindow.document;
var grid = docFrame.getElementById("crmGrid");
var allRecords = grid.InnerGrid.AllRecords;
for(var i=0; i
function getIframe()
{
return document.getElementById("wraperActivitiesFrame");
}
/script>
/HEAD>
body >
iframe id="wraperActivitiesFrame" src="/workplace/home_activities.aspx" WIDTH="100%" HEIGHT="100%" onreadystatechange="Run()">
/HTML>
The issue I am having now is that the function does not run again when I try to page the grid. I have 2 pages of Activities; when the page loads for the first time - I have my alert boxes, but when I click on "page 2" arrow - nothing happens. Why??? What I am doing wrong?
You kinda can hook into that event. You create a "wrapper" HTML page that you load in CRM instead of the default activities grid via Sitemap. This wrapper contains a full-size IFrame in which you load the actual grid, and in the IFrame's onreadystatechange handler (for readyState == 4), you traverse the grid's DOM (jQuery might make this a little easier, but I haven't used jQuery much myself) and do whatever changes you need to do (that means the JavaScript goes within the wrapper HTML page). If you call this via setInterval and put a try-catch around it, this will even be safe against grid refreshes and browsing through the pages.