AngularJS : router : load view manually from within controller - animation

Is there a way of manually loading the view from within the controller, after say some animation was triggered first? The scenario I have is the previous page content sliding up, after that the view would be updated when being off-the screen and once ready - slides back down with the new view from the new controller.
I've got already the router set up, but it just instantly replaces the view whenever the new controller is called.
Any fiddle if possible please?

Code in Controller shouldn't manipulate DOM, directives should. Here is directive to prevent preloading content of element with "src" (by browser's parser) and show content of element only after loading, and before loading show splash with spinner:
directive('onloadSrc', function($compile) {
return function(scope, element, attrs) {
element.bind('load', function() {
var parent = $compile(element[0].parentElement)(scope);
if (!element.attr('src') && attrs.onloadSrc) {
element.attr("src", attrs.onloadSrc);
// replace this dirty hardcode with your template for splash spinner
var spinner_div = $compile('<div style="z-index: 100; width: '+element.attr('width')+'px; height: '+element.attr('height')+'px; display:block; vertical-align:middle;"><img src="/img/spinner.gif" style="position: absolute; left: 50%; top: 50%; margin: -8px 0 0 -8px;"/></div>')(scope);
attrs.onloadSrc = "";
parent.prepend(spinner_div);
element.css("display", 'none');
attrs.xloading = spinner_div;
}
else {
if (attrs.xloading) {
attrs.xloading.remove();
attrs.xloading = false;
element.css("display", 'block');
}
}
}
);
}});
To use this directive, leave empty attribute src of element and fill attribute onload-src.

Angular has animations build in in unstable branch, which should perfectly fit your scenario.
Just check out http://www.nganimate.org/angularjs/tutorial/how-to-make-animations-with-angularjs.
ng-view directive has build in 'enter' and 'leave' animations.
Check you this sample: http://jsfiddle.net/nFhX8/18/ which does more less what you'd like to achieve.

Related

kendo ui - override k-animation-container style for one dropdown only

I use kendo-ui dropdown.
I add some ovveriding-css, and it works well.
.k-animation-container {
//this is popup that is html is rendered out of the page element
//so it cannot be selected by id / panaya class / panaya element
.k-popup.k-list-container {
.k-item,
.k-item.k-state-selected,
.k-item.k-state-focused {
background-color: transparent;
color: $darken-gray-color;
margin-left: 0;
margin-top: 0;
}
}
}
The problem is, that while each dropdown has other input element instance, the list has one instance that is hidden and when you click any combo - is shown near the currently clicked combo.
What say - when you ovveride the list-container style - dows it for all of the combooxes.
Is there any solution for this issue?
Well this is a known problem, for every popup kendo renders independent div with class k-animation-container
You can try with this solution suggested on telerik forum:
k-animation-container
$("#spreadsheet").on("click", ".k-spreadsheet-editor-button", function(e) {
var animationContainer = $(".k-animation-container").last();
// use some custom conditional statement that will determine if this is the correct list popup, e.g. check what's inside the popup
if (true) {
animationContainer.children(".k-popup").css("min-width", 200);
}
});
Didn't try it my self, gl.
One solution I found was to use
popup: {
appendTo: $(some parent with ID)
}
This way we can manipulate styling of that particular .k-animation-container.
But this doesn't work on every widget, unfortunately.
My team find a great solution:
There is an option to give the input-element custom id.
Then you can select the list-container by the custom id you gave +'list' str.
Now, if you want to get the k-animation-container, you can select the list element and then request its parent.
Code sample:
The input element:
<span
kendo-multi-select
id="my-type-dd"
k-options="$ctrl.getVMultySelectConfig()"
k-ng-model="$ctrl.selectedTypes"
></span>
Selectors:
If you need only the k-list-container and not must the k-animation-container, you can do that by css:
.k-animation-container #my-type-dd-list {
//this is popup that is html is rendered out of the page element
//the id is the id you give to the element + '-list'
&.k-popup.k-list-container {
padding: $space-normal 0 $space-small $space-small;
box-shadow: 3px 3px 1px rgba(0, 0, 0, 0.1);
}
}
If you need the k-aniamation-container you need to select it by jQuery becouse css doesn't have parent selector:
var kAnimationElement = $("#my-type-dd-list").parent();

Telerik Words Processing - No line strike through from HTML to PDF

I am working with Telerik Word Processing (WP) and in some instances the HTML output on screen has a line strike through to show that an event is cancelled.
Because of how the WP works, it cannot use CSS in the standard way using links and relative paths so am using style tags in the CSHTML file.
If in the page I use
.cancelled-event {
color: #c82333;
text-decoration: underline !important
}
The text is underlined and is coloured correctly, if I use
.cancelled-event {
color: #c82333;
text-decoration: line-through !important
}
I just get the text the right colour.
Overline also does not work, however only tested this to ensure that Im not being an idiot (doesn't mean Im not, but still one of the easy checkables)
What I would like help with is,
Has anyone else experienced this? If so how did you resolve it,
What other suggestions, is there to get
The CSHTML page is as below, munis code that will bloat this question.
<style>
.date-selection {
border: 1px solid #8c8c8c;
background-color: #ffffff
}
.cancelled-event {
color: #c82333;
text-decoration: line-through !important
... more styles here...
}
</style>
<img src="http://localhost:8001/images/logo.png" />
<br/>
<partial name="~/Views/Roster/_RosterAgenda.cshtml" model="#Model" />
I konw the strike through does show in 2/3 scenarios.
In view - works
In view where export should be as I have an exit where I can push the data to a view before pdf - works
In PDF - doesnt work.
PDF Generation is being done like this, the byte array that is passed in is base 64 encoded as the original file information is being passed from one System to an API over the wire.
public byte[] ConvertHtmlToPdf(byte[] fileData, string extension, PageSettings.PageOrientation orientation)
{
byte[] convertedData = null;
var base64EncodedBytes = Convert.FromBase64String(Encoding.Default.GetString(fileData));
var html = Encoding.UTF8.GetString(base64EncodedBytes);
HtmlFormatProvider htmlProvider = new HtmlFormatProvider();
RadFlowDocument document = htmlProvider.Import(html);
IFormatProvider<RadFlowDocument> provider = this.providers
.FirstOrDefault(p => p.SupportedExtensions
.Any(e => string.Compare(extension, e, StringComparison.InvariantCultureIgnoreCase) == 0));
if (provider == null)
{
Log.Error($"No provider found that supports the extension: {extension}");
return null;
}
var quality = Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.Export.ImageQuality.Medium;
PdfFormatProvider formatProvider = new PdfFormatProvider();
formatProvider.ExportSettings.ImageQuality = quality;
if (document.Sections.Any())
{
foreach (var section in document.Sections)
{
//section.PageOrientation = orientation == PageSettings.PageOrientation.Landscape ? PageOrientation.Landscape : PageOrientation.Portrait;
section.Rotate(orientation == PageSettings.PageOrientation.Landscape ? PageOrientation.Landscape : PageOrientation.Portrait);
}
}
using (var stream = new MemoryStream())
{
formatProvider.Export(document, stream);
convertedData = stream.ToArray();
}
return convertedData;
}
I found a better, easier, nicer way, but this only works if you have the Kendo Tools license too.
$(".export-pdf").click(function() {
// Convert the DOM element to a drawing using kendo.drawing.drawDOM
kendo.drawing.drawDOM($(".content-wrapper"))
.then(function(group) {
// Render the result as a PDF file
return kendo.drawing.exportPDF(group, {
paperSize: "auto",
margin: { left: "1cm", top: "1cm", right: "1cm", bottom: "1cm" }
});
})
.done(function(data) {
// Save the PDF file
kendo.saveAs({
dataURI: data,
fileName: "HR-Dashboard.pdf",
proxyURL: "https://demos.telerik.com/kendo-ui/service/export"
});
});
});
As per usual Telerik documentation is awful, and to find anything you want you almost have to start looking for something else. However, this code was found at
https://www.telerik.com/blogs/5-ways-export-asp-net-word-pdf-file
The benefit of this, and once again this only works if you have UI for xxx. In this instance I am using UI for ASP.Net Core and also using Typescript which needed a modification to the definately typed file kendo.all.d.ts too.
function drawDOM(element: JQuery, options: any): JQueryPromise<any>; //Existing code in the d.ts file
function drawDOM(element: JQuery<HTMLElement>);
function drawDOM(element: any, options?: any): JQueryPromise<any>;
But this is \ was down to not passing in a type of jquery object of HTMLElement. This makes it a little more robust enabling you to pass more into it.
I suspect that this answer will only be of use to a small number of people, however, hopefully this will help someone in the future.

Dojo class event listener disappears upon subsequent instantiation

I have a simple class called Draggable, which has a Moveable and a click event listener:
define([
'dojo/dom',
'dojo/query',
'dojo/dom-style',
'dojo/dnd/Moveable',
'dojo/_base/declare'
], function(
dom,
query,
domStyle,
Moveable,
declare
){
return declare(null, {
constructor: function(id){
this.id = id;
dom.byId('draggables').innerHTML +=
'<div id="' + id + '" style="width: 100px; height: 100px; border: 1px solid #000;"></div>';
this.moveable = new Moveable(id, {
handle: dom.byId(id)
});
query('#' + id).on('click', function(){ console.log(id); });
}
});
});
In the main HTML file, index.html, I simply create two instances of Draggable, A and B:
<script>
require([
'dojo',
'dojo/query',
'extras/Draggable'
], function(
query,
Draggable
){
var a = new Draggable('A');
var b = new Draggable('B');
});
</script>
If I created Draggable A alone (without creating Draggable B), I can drag Draggable A around, and whenever I click on it, the console will log "A" as expected.
However, once I create Draggables A and B (as shown in the code), only Draggable B can be dragged around, and only when I click on Draggable B will the console log "B". It seems as though the moment Draggable B is created, Draggable A loses both its Moveable and its event listener!
Well, you'd better go another way. Movable class designed so you can't use it as mixin in your widget. It's constructor requires a node as parameter and templated widget don't have node at this moment, except srcNodeRef, if it was passed.
So, I'd suggest you do the following:
1 Create templated widget without Movable class. Attach your event listeners, if you need. It will work out of the box without any collisions if you properly use data-dojo-attach-event attribute or any other way you like.
Code of widget may look like:
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin"
], function (
declare,
_WidgetBase,
_TemplatedMixin
) {
"use strict";
return declare("Draggable", [_WidgetBase, _TemplatedMixin], {
templateString: "<div data-dojo-attach-event='click: clickHandler' style='width: 100px; height: 100px; border: 1px solid #000'>draggable div</div>",
clickHandler: function (e) {
console.log("Clicked:", this.id, e);
}
});
});
2 Somewhere in your page you'll create your widgets and make them movable like:
<script>
require(["dojo/dnd/Moveable", "Draggable"], function (Movable, Draggable){
let d1 = new Draggable();
d1.placeAt("myContainer");
let d2 = new Draggable();
d2.placeAt("myContainer");
let m1 = new Movable(d1.domNode);
let m2 = new Movable(d2.domNode);
});
</script>
<div id="myContainer"></div>
I've tested, it worked for me. Hope it'll help;

In firefox, the code in iframe of my website can't be loaded properly, but success to be loaded if the iframe is unhidden and reload the iframe again

Hope my Question is enough clear. I own a website.
http://khchan.byethost18.com
My problem is in the tab "Calendar", it run properly in chrome, ie. but not in fixfox.
my design is that when I hover the calendar tab. the page of calendar will show.
but in firefox, when I do that, it don't show properly. developer tool show $bookblock.bookblock is not a function. If I reload the frame, such error message will not show.
If I directly load "http://khchan.byethost18.com/cal.php
It can show properly and such error message don't appear.
so I guess may be something is not load properly. I already try add $(top.document,document).ready({function(){}); or replace the jquery library to the head or body. the problem still exist.
since the coding is very long. I only write the iframe tag.Please try to use developer tool to view my code.
I tried document.getElementById('CalF').contentWindow.location.reload();
if I already hover the calendar tab, the tab can be reload properly.
but if not, the developer tool display the same error message.
so, I think the major key to the problem is that the jquery tab affect something so that the tab "CalF" can't work properly.
.boxoff{
display: none;
}
<article class='boxoff'> //this article will be hidden until I delete the class.
<iframe id=CalF src="cal.php" style="top: 0;"></iframe>
</article>
Thanks.
iframeLoaded()
Update 2
OP explained that the iframe must be invisible initially. While this may seem an impossibility since iframes do not load when it or one of it's ancestor elements are display: none;. The key word is invisible which is a state in which the iframe is not visible.... There are three CSS properties that come to mind and one of them is actually shouldn't be used in this situation.
display: none; This is the property being used by OP and this property actually hinders the iframe's loading. The reason why is when in that state of invisibility, the iframe is not in the DOM according to Firefox's behavior.
opacity: 0; This property renders the iframe invisible as well and Firefox seems to recognize the invisible iframe just fine.
visibility: hidden; This seems to be an acceptable as well....
So try this code that I use to suppress the FOUC:
Child Page
function init(sec) {
var ms = parseFloat(sec * 1000);
setTimeout('initFadeIn()', ms);
}
function initFadeIn() {
$("body").css("visibility","visible");
$("body").fadeIn(500);
}
HTML
<body style="visibility: hidden;" onload="init(2);">
Update 1
I made an alternative solution because I hate leaving a demo that doesn't completely work★.
Ok this relies on cal.php window.onload event which is basically the slowest but the most stablest phase of loading there is.
Initially, #overlay will block any user interaction while calF is loading.
Once calF is completely loaded, it will call iframeLoaded function that's located on the parent page.
iframeLoaded will remove #overlay (I added a setTimeout for good measure but it's probably not necessary.)
I'm not that familiar with PHP syntax, so you'll have to modify the following code✶ and place it in cal.php
window.onload = function() {
parent.iframeLoaded();
}
Then on the parent page:
function iframeLoaded() {
setTimeout(function() {
$('#overlay').hide(750);
}, 1500);
}
The code above as well as the required HTML and CSS is in the snippet below.
★ Note: The code in the snippet should work, but this snippet won't of course because there's some code that needs to be on the child page. That's just a shoutout to all the downvoters out there ;-)
Snippet 1
// iframeLoaded will remove the overlay when cal.php has completely loaded
function iframeLoaded() {
setTimeout(function() {
$('#overlay').hide(750);
}, 1500); //<========[1 to 2 (1000 - 2000ms) seconds should give you plenty of time]
}
/*~~~~~~~~~~~~~~~~~~~~~~~~[Code in cal.php]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// When everything (DOM, script, images. etc...) is loaded on cal.php, call iframeLoaded function that is on the parent's page.
window.onload = function() {
parent.iframeLoaded();
}
#overlay {
background: rgba(0, 0, 0, .3);
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
#CalF {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="overlay"></div>
<iframe id="CalF" src="http://khchan.byethost18.com/cal.php" height="100%" width="100%" frameborder="0" style="top: 0;"></iframe>
✶ Function loadedIframe() inspired by SO5788723
Snippet 2
document.getElementById('CalF').onload = function(e) {
var over = document.getElementById('overlay');
over.classList.add('hide');
}
#overlay {
background: rgba(0, 0, 0, .3);
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
.hide {
display: none;
}
#CalF {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="overlay"></div>
<iframe id="CalF" src="http://khchan.byethost18.com/cal.php" height="100%" width="100%" frameborder="0" style="top: 0;"></iframe>
$(document).ready seems to be called too soon, based on parent page instead of iframe content.
here you have solution to a similar problem:
jQuery .ready in a dynamically inserted iframe

Optimizing AngularJS directive that updates ng-model and ng-style on focus

I'm new to AngularJS and I'm making made a couple of custom Angular directives to do what I used to do with Jquery, however there is one case where I'm not sure if I'm doing it the "the angular way". It works but I think there might be a better way.
I want to do is this for a search box:
When focus is on the search box the app must change the color of the text in the box from grey to black. The app must also then check the current text in the box, if it is the default text then the app must clear the text.
When the box loses focus (blur) the app must change the box's text back to grey. It must then put back the default text only if the text box is empty upon losing focus.
Here is a jsfiddle that has a directive set up to do all of this perfectly.
http://jsfiddle.net/Rick_KLN/5N73M/2/
However I suspect there is an even better way to do it.
It seems like all three those variables in the controller should be unnecessary.
I also seems like having 4 if, else statements is too much and that binding to all the events is overkill seeing as only focus and blur are used and they are specified in the if statements.
Any ideas on optimizing this directive?
The "default text" behavior you are looking for is automatically handled by the HTML5 placeholder attribute. It is supported in just about any modern browser, and can be styled using CSS, as follows:
Markup:
<input id="searchBar" type="text" placeholder="Search" />
CSS:
#searchBar { color: #858585; }
#searchBar:focus { color: #2c2c2c; }
#searchBar:focus::-webkit-input-placeholder { color: transparent; }
#searchBar:focus::-moz-placeholder { color: transparent; }
#searchBar:focus:-moz-placeholder { color: transparent; }
#searchBar:focus:-ms-input-placeholder { color: transparent; }
It's that simple.
Notes:
The pseudo-elements & pseudo-classes (-webkit-input-placeholder, etc) are what hide the placeholder text on focus. Normally it stays until you start typing.
I forked your original jsFiddle. It's not really an AngularJS app anymore:
http://jsfiddle.net/Smudge/RR9me/
For older browsers: You can still use the same code as above, but you could use Modernizr (or something similar) to fall-back to a javascript-only approach if the attribute is not supported.
You can create a custom directive that requires the ng-model directive and then within your directive's link function supply a fourth parameter that is a reference to the model. This will allow you to watch the model for changes and react accordingly. Here is the fiddle:
http://jsfiddle.net/brettlaforge/6t39j/3/
var app = angular.module('app', []);
app.directive('searchbar', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, model) {
var options = scope.$eval(attrs.searchbar);
scope.$watch(attrs.ngModel, function(value) {
// If the input element is currently focused.
if (!elm.is(":focus")) {
// If the input is empty.
if (value === undefined || value === "") {
// Set the input to the default. This will not update the controller's model.
elm.val(options.default);
}
}
});
elm.on('focus', function(event) {
// If the input is equal to the default, replace it with an empty string.
if (elm.val() === options.default) {
elm.val('');
}
});
elm.on('focusout', function(event) {
// If the input is empty, replace it with the default.
if (elm.val() === '') {
elm.val(options.default);
}
});
}
};
});
function FormCtrl($scope) {
$scope.search = "";
}​

Resources