How to refresh an image after src change in Angular JS - image-processing

I would like to selecta file and load it in angular js.
Everything work fine, the only problem the image don't refrech. I can see that everything work because when i toggle the on menu on my page with angular.js the image is been refreshing.
Here is my code :
<div ng-controller="TopMenuCtrl">
<button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
<input ng-model="photo"
onchange="angular.element(this).scope().file_changed(this)"
type="file" accept="image/*" multiple />
<output id="list"></output>
<img ng-src="{{imageSource}}">
</div>
And the Angular js script :
$scope.file_changed = function(element) {
var files = element.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, photofile; photofile = files[i]; i++) {
// var photofile = element.files[0];
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
$scope.imageSource= e.target.result;
};
})(photofile);
reader.readAsDataURL(photofile);
};
}

You must call Scope.$apply when you manually update $scope.imageSource in the onLoad function, because Angular can't guess when you make this change.

Related

Image map area tooltip on title

Im trying to make an image map and i need a tooltip to be showed on mouse hover. the html code is like below.
`<div id="harta">
<img src="/templates/it_thecity/images/map.png" width="620" height="310" class="map" border="0" usemap="#shqiperia" />
<map name="shqiperia" id="shqiperia">
<area shape="poly" coords="266,69,260,74,260,82,255,90,251,97,246,98,246,104,240,103,239,107,240,113,237,116,239,121,243,121,248,123,251,120,252,114,256,115,260,117,263,114,263,109,263,105,265,104,268,104,269,100,271,96,272,91,270,89,267,81,267,75,266,69" href="#" target="_self" alt="Shkodra" title="Shkodër (3)" class="sh masterTooltip" data-maphilight='{"groupBy":".sh"}'/>
<area shape="rect" coords="44,56,122,76" href="#" alt="Shkodër" class="sh masterTooltip" data-maphilight='{"groupBy":".sh","fill":false, "stroke":false}' title="3 Universitete" />
</div>`
And I have a javascript code from a module in my site that show some tooltips on other elements not in image map.
`<script type="text/javascript">
window.addEvent('domready', function() {
$$('.hasTip').each(function(el) {
var title = el.get('title');
if (title) {
var parts = title.split('::', 2);
el.store('tip:title', parts[0]);
el.store('tip:text', parts[1]);
}
});
var JTooltips = new Tips($$('.hasTip'), { fixed: false});
});
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>`
How do I make a tooltip appear on mouse hover on the area elements?
Resolved this question time ago but have forgot to put the answer on.
Here is the solution:
[http://jsfiddle.net/ove4trwa/4/][1]

Preview an image before it is saved to database in Yii using Jquery

I am not understanding how should I carry on to Preview an image before it is
being saved to database in yii using jquery or any method that you can suggest
view
<img id="preview_image"
src="images/<?php echo $model->pimg; ?>"
width="150px" height="120px"/>
<?php echo $form->labelEx($model,'pimg'); ?>
<?php echo $form->fileField($model, 'pimg',array('change'=>preview(this));); ?>
<?php echo $form->error($model,'pimg'); ?>
the jquery code
function preview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#preview_image')
.attr('src', e.target.result)
.width(100)
.height(120);
};
reader.readAsDataURL(input.files[0]);
}
}
Fatal error to function call preview().
How should I integrate this Jquery function in above form ....... $form has the htmlOptions
PLEASE HELP! I am new to Yii and am loosing my mind on this. Thank you.
This bellow code shows the image preview using jQuery
var imageTypes = ['jpeg', 'jpg', 'png']; //Validate the images to show
function showImage(src, target)
{
var fr = new FileReader();
fr.onload = function(e)
{
target.src = this.result;
};
fr.readAsDataURL(src.files[0]);
}
var uploadImage = function(obj)
{
var val = obj.value;
var lastInd = val.lastIndexOf('.');
var ext = val.slice(lastInd + 1, val.length);
if (imageTypes.indexOf(ext) !== -1)
{
var id = $(obj).data('target');
var src = obj;
var target = $(id)[0];
showImage(src, target);
}
else
{
}
}
And your HTML should be
<input type="file" name="image" onchange="uploadImage(this)" data-target="#aImgShow" />
<img id="aImgShow" src="" class="carImage" />

JQueryUI dialog as bindable template in KnockoutJS

This question is exposing that one: integrating jquery ui dialog with knockoutjs
I have Model with array of items like this:
var viewModel = {
items: ko.observableArray([])
}
viewModel.items.push(new DialogModel("title 1"));
viewModel.items.push(new DialogModel("title 2"));
viewModel.items.push(new DialogModel("title 3"));
Next I show these items in markup using foreach statement
<div data-bind="foreach: items">
<div data-bind="text: title"></div>
<button data-bind="click: open">Open</button>
<button data-bind="click: close" >Close</button>
</div>
I need to show JQueryUI dialog on clicking buttons and this dialog should be binded to ItemModel instance.
I do not want to include dialog code inside loop because it is copying in result DOM and makes it huge. I'd like to use dialog in template for example.
JSFiddle mockup here http://jsfiddle.net/YmQTW/8/
Any thoughts?
You can create an array that contains only the opened dialogs and bind this array to the template.
With this code only dom of opened dialogs are duplicated.
var DialogModel = function (title) {
var self = this;
self.title = ko.observable(title);
self.isOpen = ko.observable(false);
self.open = function () {
viewModel.shownDialogs.push(self);
setTimeout(function () { self.isOpen(true); }, 0);
};
self.close = function () {
this.isOpen(false);
};
self.isOpen.subscribe(function () {
if(self.isOpen() === false)
viewModel.shownDialogs.remove(self);
})
};
var viewModel = {
items: ko.observableArray([]),
shownDialogs: ko.observableArray([]),
};
The view :
<div data-bind="foreach: shownDialogs">
<div data-bind="template : 'tmpl'"></div>
</div>
See fiddle
I hope it helps.

LocalStorage Values not updated on Page Show in multipage mobile app using phonegap and jquery(-mobile)

I have a multipage mobile app using phonegap, leaflet and jquery(-mobile) and the following problem:
On page1, when clicking on a map-marker, the name of the poi is written to localstorage and then page2 is called:
var onMarkerClick = function(e) {
akt_poi = e.layer.options.poi;
var globVars = {
"akt_poi": akt_poi,
};
localStorage.setItem('globalVariables', JSON.stringify(globVars));
window.location = '#page2';
};
On page2 i'm doing the following:
<div data-role="content">
<div id=poi></div>
<script type="text/javascript">
var gV = JSON.parse(localStorage.getItem("globalVariables"));
var a_poi = gV.akt_poi;
document.getElementById("poi").innerHTML='<h2>'+a_poi+'</h2>';
</script>
The correct value is shown only at the first call. When doing another click on a map-marker of page1 the old value instead of the locally stored one is shown on page2 until doing a page-refresh.
What can i do display the right value?
I solved the problem by using sessionstorage:
setting on page1:
var onMarkerClick = function(e) {
akt_poi = e.layer.options.poi;
sessionStorage.akt_poi=akt_poi;
window.location = '#page2';
};
reading on page2:
<div data-role="content">
<div id=poi></div>
<script type="text/javascript">
$('#page_audio').live('pageshow', function(event, ui) {
document.getElementById("poi").innerHTML='<h2>'+sessionStorage.akt_poi+'</h2>';
});
</script>

knockout.js and jQueryUI to create an accordion menu

Got a slight problem trying to have jquery UI and knockout js to cohoperate. Basically I want to create an accordion with items being added from knockout through a foreach (or template).
The basic code is as follows:
<div id="accordion">
<div data-bind="foreach: items">
<h3></h3>
<div><a class="linkField" href="#" data-bind="text: link"></a></div>
</div>
</div>
Nothing impressive here... The problem is that if I do something like:
$('#accordion').accordion();
The accordion will be created but the inner div will be the header selector (first child, as default) so the effect is not the wanted one.
Fixing stuff with this:
$('#accordion').accordion({ header: 'h3' });
Seems to work better but actually creates 2 accordions and not one with 2 sections... weird.
I have tried to explore knockout templates and using "afterRender" to re-accordionise the div but to no avail... it seems to re-render only the first link as an accordion and not the second. Probably this is due to my beginner knowldge of jquery UI anyway.
Do you have any idea how to make everything work together?
I would go with custom bindings for such functionality.
Just like RP Niemeyer with an example of jQuery Accordion binding to knockoutjs http://jsfiddle.net/rniemeyer/MfegM/
I had tried to integrate knockout and the JQuery UI accordion and later the Bootstrap collapsible accordion. In both cases it worked, but I found that I had to implement a few workarounds to get everything to display correctly, especially when dynamically adding elements via knockout. The widgets mentioned aren't always aware of what is happening with regards to knockout and things can get messed up (div heights wrongly calculated etc...). Especially with the JQuery accordion it tends to rewrite the html as it sees fit, which can be a real pain.
So, I decided to make my own accordion widget using core JQuery and Knockout. Take a look at this working example: http://jsfiddle.net/matt_friedman/KXgPN/
Of course, using different markup and css this could be customized to whatever you need.
The nice thing is that it is entirely data driven and doesn't make any assumptions about layout beyond whatever css you decide to use. You'll notice that the markup is dead simple. This is just an example. It's meant to be customized.
Markup:
<div data-bind="foreach:groups" id="menu">
<div class="header" data-bind="text:name, accordion: openState, click: toggle"> </div>
<div class="items" data-bind="foreach:items">
<div data-bind="text:name"> </div>
</div>
</div>
Javascript:
ko.bindingHandlers.accordion = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
$(element).next().hide();
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var slideUpTime = 300;
var slideDownTime = 400;
var openState = ko.utils.unwrapObservable(valueAccessor());
var focussed = openState.focussed;
var shouldOpen = openState.shouldOpen;
/*
* This following says that if this group is the one that has
* been clicked upon (gains focus) find the other groups and
* set them to unfocussed and close them.
*/
if (focussed) {
var clickedGroup = viewModel;
$.each(bindingContext.$root.groups(), function (idx, group) {
if (clickedGroup != group) {
group.openState({focussed: false, shouldOpen: false});
}
});
}
var dropDown = $(element).next();
if (focussed && shouldOpen) {
dropDown.slideDown(slideDownTime);
} else if (focussed && !shouldOpen) {
dropDown.slideUp(slideUpTime);
} else if (!focussed && !shouldOpen) {
dropDown.slideUp(slideUpTime);
}
}
};
function ViewModel() {
var self = this;
self.groups = ko.observableArray([]);
function Group(id, name) {
var self = this;
self.id = id;
self.name = name;
self.openState = ko.observable({focussed: false, shouldOpen: false});
self.items = ko.observableArray([]);
self.toggle = function (group, event) {
var shouldOpen = group.openState().shouldOpen;
self.openState({focussed: true, shouldOpen: !shouldOpen});
}
}
function Item(id, name) {
var self = this;
self.id = id;
self.name = name;
}
var g1 = new Group(1, "Group 1");
var g2 = new Group(2, "Group 2");
var g3 = new Group(3, "Group 3");
g1.items.push(new Item(1, "Item 1"));
g1.items.push(new Item(2, "Item 2"));
g2.items.push(new Item(3, "Item 3"));
g2.items.push(new Item(4, "Item 4"));
g2.items.push(new Item(5, "Item 5"));
g3.items.push(new Item(6, "Item 6"));
self.groups.push(g1);
self.groups.push(g2);
self.groups.push(g3);
}
ko.applyBindings(new ViewModel());
Is there any reason why you can't apply the accordion widget to the inner div here? For example:
<div id="accordion" data-bind="foreach: items">
<h3></h3>
<div><a class="linkField" href="#" data-bind="text: link"></a></div>
</div>
I attempted the accepted solution and it worked. Just had to make a little change since i was getting following error
Uncaught Error: cannot call methods on accordion prior to initialization; attempted to call method 'destroy'
just had to add following and it worked
if(typeof $(element).data("ui-accordion") != "undefined"){
$(element).accordion("destroy").accordion(options);
}
for details please see Knockout accordion bindings break
You could try this to template it, similar to this:
<div id="accordion" data-bind="myAccordion: { },template: { name: 'task-template', foreach: ¨Tasks, afterAdd: function(elem){$(elem).trigger('valueChanged');} }"></div>
<script type="text/html" id="task-template">
<div data-bind="attr: {'id': 'Task' + TaskId}, click: $root.SelectedTask" class="group">
<h3><b><span data-bind="text: TaskId"></span>: <input name="TaskName" data-bind="value: TaskName"/></b></h3>
<p>
<label for="Description" >Description:</label><textarea name="Description" data-bind="value: Description"></textarea>
</p>
</div>
</script>
"Tasks()" is a ko.observableArray with populated with task-s, with attributes
"TaskId", "TaskName","Description", "SelectedTask" declared as ko.observable();
"myAccordion" is a
ko.bindingHandlers.myAccordion = {
init: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion(options);
$(element).bind("valueChanged", function () {
ko.bindingHandlers.myAccordion.update(element, valueAccessor);
});
...
}
What I did was, since my data was being loaded from AJAX and I was showing a "Loading" spinner, I attached the accordion to ajaxStop like so:
$(document).ajaxStart(function(){$("#cargando").dialog("open");}).ajaxStop(function(){$("#cargando").dialog("close");$("#acordion").accordion({heightStyle: "content"});});
Worked perfectly.

Resources