Why I can't use ng-click into jQueryDialog - javascript

I want to create a div who can change the background dynamically with jquery and angularjs.
When I click on the text inside background, it open a new windows (Jquery ui Dialog) and I can choose another background image.
When I click on the image, I would like change background!
I have two questions:
Why I can't use ng-click into dialog dynamic content?
I have a dialog with dynamic data:
$( "#dialog" ).load( item+".html" ).dialog( "open" );
The data that have been loaded:
<img ng-controller="BackgroundCtrl" src="http://etickets.dev10.dev.infomaniak.ch/images/templates/background.jpg" width="20%" height="20%" ng-click="changeBackground.doClick('http://etickets.dev10.dev.infomaniak.ch/images/templates/background.jpg')" />
When I put data direclty into dialog div, I use ng-click directive.
The second questions is:
When I click, I update
$scope.BackGroundImage
Why the div don't change his background image?
The full exemple is here:
http://plnkr.co/edit/?p=streamer&s=og6gLDAeSNgi6clQ

As I understand it you are trying to build dynamic HTML with jQuery and expect Angular to understand it.
That does not work. Angular needs to know about everything that is going on, so building content "outside" of Angular is a problem.
To tell Angular about the new HTML content do something like:
$("#dialog").load(item+".html", function () {
var $this = $(this);
var html = $this.html();
var angularCompiled = $compile(html)($scope);
$this.html(angularCompiled);
}).dialog("open");
This is only theory and there are probably other ways to do this also, but this gives you an idea.

Related

Toggle script: change from jQuery to "normal javascript" code

I've been using a toggle script (open/close text container when clicking on a certain link) for a website that uses jQuery. In order to clean up the website I want to get rid of jQuery completely but have some problems converting the existing jQuery code into "normal javascript".
Here is the existing code:
jQuery(function($){
$(document).ready(function(){
$(".toggle_container").hide();
$("h4.trigger").click(function(){
$(this).toggleClass("active").next().slideToggle("normal");
return false; //Prevent the browser jump to the link anchor
});
});
});
Which corresponds to this HTML source code:
<h4 class="trigger toggle-transparent ">Click to show more</h3><div class="toggle_container ">
Hidden Text
</div>
I've tried the following code which doesn't give me an error but just doesn't do anything when clicking on the trigger:
var el = document.querySelectorAll('h4.trigger');
for(var i=0; i < el.length; i++){
el[i].addEventListener('click', function () {
this.classList.toggle("active").nextSibling.classList.toggle("toggle_container-active");
}.bind(this));
}
The only thing I really need for the code is: clicking on the class "trigger" should toggle some HTML class "active" to both the trigger element as well as the toggle_container element. The rest I'm able to change with just CSS.
The hard part of the code is that it should work for multiple toggle areas on one page separately (therefore using a class, not an id).
Any idea where my code has a problem or any (completely) different suggestions?
I have very limited experience with javascript/jQuery and feel more at home with HTML/CSS.
Thanks,
Patrick
The this.classList.toggle("active") doesn't return the element back again, but just a boolean to inform if the action was successful. Chaining happens only in jQuery and not in vanilla JavaScript.
this.classList.toggle("active").nextSibling.classList.toggle("toggle_container-active");
You should be using something like this instead of the above:
this.classList.toggle("active");
this.nextSibling.classList.toggle("toggle_container-active");

Javascript - Click list element to load HTML page animation

Javascript novice here. I am working on a piece of code provided here - http://codepen.io/mariusbalaj/pen/beALH/
I'm trying to modify the behavior so that instead of just zooming in the list element when clicked, it should load a different html page within the animated frame.
$(document).ready(function() {
var $box = $('.box');
$('.metro li').each(function() {
var color = $(this).css('backgroundColor');
var content = $(this).html();
$(this).click(function() {
$box.css('backgroundColor', color);
$box.addClass('open');
$box.find('p').html(content);
});
$('.close').click(function() {
$box.removeClass('open');
$box.css('backgroundColor', 'transparent');
});
});
});
Can anyone point me to the right direction?
Update 1 :
I figured out that modifying the 'content' variable on the below line would change the content of the animated frame:
` $box.find('p').html(content);`
And if I change it to something like:
` $box.find('p').html('<h1>Test Page</h1>');`
It works as expected. However, I want the content to be different for each list element.
Is there an easy way of doing this per element? I am quite confused with the 'this' keyword.
You may be looking for this answer, if you want to open another HTML page:
how to change page from within javascript
If you're trying to open it WITHIN the animated frame, you should look into making some requests to the content of the new page/tile and filling that with content, which is answered here: How to get the response of XMLHttpRequest?
It all depends what you want to do, let us know :)

Angularjs - Resize bootstrap modal after modal is shown

I am still fairly new to angularjs and am currently porting a existing spa javascript application to the angularjs framework. I am using the ui-bootstrap directive for creating bootstrap modals. I am trying to re-position the modal in the middle of the screen once the modal is displayed on the screen. With jQuery that was a easy task, just grab the modal element after calling:
$('#modal').modal('show')
But I can't seem to figure out the correct way to do this using angular. My first thought was to catch bootstrap events. But it turns out those are not fired according to
Here
and
Here
I tried creating a custom directive, but in the link function the element was defined but was not visible on the screen yet. I need a way to trigger some resize code once the modal is visible.
I also tried accessing the $modalStack.getTop(), but I end up having the same issue. There is no way to know when $modalStack.getTop().value.modalDomEl is actually resolved and showing on the screen.
I also tried the following, but the opened promise is resolved before the modal is actually showing on the screen.
modalInstance.opened.then(function(t){
//$modalStack.getTop()
});
How do you accomplish this using angular?
So I ended up taking what #user2943490 recommended and tweaked it a little bit for my use case.
I created a directive that I added to the Modal Template. Inside I check every 100ms to see if the modal-content class exists. If the class exists we know that the modal has bee added to the DOM. Once I perform my logic, I cancel the $interval check.
return {
link: function(scope, element, attrs){
var checkInterval = $interval(checkDOM, 100);
function checkDOM(){
var $content = element.find('.modal-content');
if($content.length){
//We know if $content.length > 0 Then the modal-content class exists on the screen.
$interval.cancel(checkInterval);
}
}
element.on('$destroy', function(){
$interval.cancel(checkInterval);
});
You should use CSS to position the modal as a first option. This avoids all issues around the timing of when specific elements get rendered and stays in line with Angular's spirit of using data binding rather than manual DOM manipulation to build your UI.
You won't find many things in the Angular world that give you an "element rendered" event or similar. It's just not the recommended way to do things.
If you absolutely cannot use CSS, then use a $timeout within the opened promise, and wait a short time (50ms is probably fine) before executing your repositioning logic.
modalInstance.opened.then(function(t){
$timeout(function () {
// reposition it
}, 50);
});
You should have used modal.rendered instead of modal.opened. No need for a link function or interval checks or anything else.
modalInstance.rendered.then(function () {
$('.modal-content').css({ 'width': $(document).width() - 100 + 'px' });
});

How to change content of a bootstrap popover that has already been displayed?

I have a form with a password entered twice. I check password complexity and consistency and display appropriate error messages into a popover attached to the INPUT field:
<a href="#" id="aIdPwd2" data-toggle="manual" data-content="The password entered does not match the one previously entered" data-placement="right" href="#" rel="popover">
<input type="password" id="iIdPwd2" class="fmt1" size="60" value=""/>
</a>
With this code:
$("#aIdPwd2").popover({content: msg});
You can chose dynamicaly the message that will be displayed. But once it has been displayed once, it will then always remain the same.
I read many articles about this popular issue and did try many things (attach 2 different popover to the same input, change the inner html in the getElementsByClassName("popover-content"), destroy and recreate the popover, ..), but without any success so far.
A solution on how to change content of a bootstrap popover that has already been displayed or any kind of work-around would be highly appreciated.
In Twitter Bootstrap 3, I just update the content and then call show. Calling of the show ensure that its resized correctly and then positioned correctly.
$(".notes").data("bs.popover").options.content="Content1";
$(".notes").popover("show");
$(".notes").data("bs.popover").options.content="Content2";
$(".notes").popover("show");
If you are using data tags to show the content then you will need to update the data tag as that takes precedence. eg.
$(".notes").attr("data-content","Content1");
$(".notes").popover("show");
$(".notes").attr("data-content","Content2");
$(".notes").popover("show");
I like the second option better coz it doesn;t access the internals by doing data(bs.popover) but the first options is much faster as it doesn't update the dom. So pick what floats your boat.
document.getElementsByClassName("popover-content")[0].innerHTML = 'something else';
sure that this doesn't work?
tried it on this page and it works as expected.
UPDATE: it will work only if the popover is visible because the element is recreated/destroyed every mouseover/mouseout event
i guess it's not the best solution, but you can do this:
var msg = 'ben123 is not a goddamn password!';
document.getElementById('password').addEventListener('mouseover', function() {
document.getElementsByClassName("popover-content")[0].innerHTML = msg;
});
and change msg when you need
The problem with solutions that rely on popover('show') is that if you do this in an event handler for the show event, you will end up with an infinite loop.
If you just want to display some content in your popover when it has already been shown, you will need to directly modify the DOM:
$("#aIdPwd2").next(".popover").find(".popover-content").html(msg);
For example, if you want a popover that will load some data from an API and display that in the popover's content on hover:
DOM:
Hover here for details
jQuery:
$("#myPopover").popover({
trigger: 'hover'
}).on('shown.bs.popover', function () {
var popover = $(this);
var contentEl = popover.next(".popover").find(".popover-content");
// Show spinner while waiting for data to be fetched
contentEl.html("<i class='fa fa-spinner fa-pulse fa-2x fa-fw'></i>");
var myParameter = popover.data('api-parameter');
$.getJSON("http://api.example.com", {
'apiParameter': myParameter
}).done(function (data) {
var result = data['apiReturnValue'];
contentEl.html(result);
}).fail(function (data) {
result = "No info found.";
contentEl.html(result);
});
});
This, of course, assumes that you trust the data supplied by api.example.com. If not, you will probably want to escape the data returned to mitigate XSS attacks.
To replace the contents of a popover on an element, first call destroy.
Tested on Bootstrap 3.1.1
$("#aIdPwd2").popover('destroy').popover({content: msg});

Monitor changes to content of html binding

I am trying to bind HTML to a div element, edit the content of that div with some sort of edit in place editor, click a save button and retrieve the new content, but I have been unsuccessful.
The view looks like this:
<div id="content" data-bind="html: content"></div>
<button data-bind="click: function(){ save() }">Save</button>
With this Javascript:
var viewModel = {
content: ko.observable("<h3>Test</h3>"),
save: function(){
console.log(ko.toJSON(viewModel));
}
}
$(function(){
ko.applyBindings(viewModel);
$("#content").html("<h4>Test</h4>");
ko.applyBindings(viewModel,document.getElementById('content'));
});
See also this jsfiddle.
When I click save the console still says <h3>Test</h3>.
Is it possible to do what I am trying to do here?
The html binding does not setup any event handlers to catch changes, as it is normally placed on elements that are not editable.
Here is a sample of using the contenteditable attribute: http://jsfiddle.net/rniemeyer/JksKx/ (from this thread).
If you are looking to integrate with an editor like TinyMCE, then here is a sample: http://jsfiddle.net/rniemeyer/GwkRQ/ (from this thread).

Categories

Resources