Modify html element in ionic - ionic-framework

My database return a field with raw html string. I'd like to modify element by adding ng-click='showImage()'. For example, the original html is:
<p>
<img src="http://mywebsite.com/img-1.jpg" />
</p>
My source code in my controller:
var parser = new DOMParser();
var doc = parser.parseFromString($scope.body, 'text/html');
var images = doc.getElementsByTagName('img')
for (var i = 0; i < images.length; i++ ) {
var img = images[i];
img.setAttribute('ng-click','showImage()');
$scope.addImage(img.getAttribute('src'));
}
$scope.body = doc.documentElement.innerHTML;
The result is correct:
<p>
<img src="http://mywebsite.com/img-1.jpg" ng-click="showImage()"/>
</p>
But I got the following error message when I click the image:
Uncaught TypeError: scope.$apply is not a function
Why? Can anybody help? Thanks.
Edit (complete source code for the controller):
(function() {
'use strict';
angular
.module('App')
.controller('DetailsController', DetailsController);
DetailsController.$inject = ['$scope','$stateParams','ParseSvc','$controller'];
function DetailsController($scope, $stateParams, ParseSvc, $controller) {
$controller('BaseController', { $scope: $scope });
$scope.article = JSON.parse($stateParams.article);
activate();
function activate() {
var parser = new DOMParser();
var doc = parser.parseFromString($scope.article.body, 'text/html');
var images = doc.getElementsByTagName('img')
for (var i = 0; i < images.length; i++ ) {
var img = images[i];
img.setAttribute('ng-click','showImages(' + i + ')');
$scope.addImage(img.getAttribute('src'));
}
$scope.article.body = doc.documentElement.innerHTML;
}
}
})();
Base controller:
(function() {
'use strict';
angular.module('App')
.controller('BaseController', ['$scope','$ionicModal','$ionicSlideBoxDelegate','$ionicScrollDelegate',
function($scope, $ionicModal, $ionicSlideBoxDelegate, $ionicScrollDelegate) {
$scope.allImages = [];
$scope.zoomMin = 1;
$scope.addImage = function(src) {
$scope.allImages.push({'src' : src});
}
$scope.showImages = function(index) {
$scope.activeSlide = index;
$scope.showModal('templates/gallery-zoomview.html');
}
$scope.showModal = function(templateUrl) {
$ionicModal.fromTemplateUrl(templateUrl, {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
$scope.modal.show();
});
};
// Close the modal
$scope.closeModal = function() {
$scope.modal.hide();
$scope.modal.remove();
};
$scope.updateSlideStatus = function(slide) {
var zoomFactor = $ionicScrollDelegate.$getByHandle('scrollHandle' + slide).getScrollPosition().zoom;
if (zoomFactor == $scope.zoomMin) {
$ionicSlideBoxDelegate.enableSlide(true);
} else {
$ionicSlideBoxDelegate.enableSlide(false);
}
}
}]);
})();

Related

How to reload/refresh with infinite-scroll

I want to have a reload function but I found some difficulties.
My app should clear all data by using the reload function and grab the feed again. Event that works, but it shows me only the first 5 news (limit of my api/per page) and ignores completely the loadMore function.
factory
.factory('newsDataService', function($http) {
return {
GetPosts: function(page) {
return $http.get("http://newsapi.domain.tdl/");
},
GetMorePosts: function(page) {
return $http.get("http://newsapi.domain.tdl/?page=" + page);
}
};
})
controller
.controller('NewsCtrl', function($scope, newsDataService) {
$scope.page = 1;
$scope.noMoreItemsAvailable = false;
newsDataService.GetPosts().then(function(items){
$scope.items = [];
$scope.items = items.data.response;
});
$scope.Reload = function() {
console.log('reload');
newsDataService.GetPosts().then(function(items){
console.log(items);
$scope.items = items.data.response ;
$scope.noMoreItemsAvailable = false;
$scope.$broadcast('scroll.refreshComplete');
})
};
$scope.loadMore = function(argument) {
$scope.page++;
newsDataService.GetMorePosts($scope.page).then(function(items){
if (items.data.response) {
$scope.items = $scope.items.concat(items.data.response);
$scope.noMoreItemsAvailable = false;
} else {
$scope.noMoreItemsAvailable = true;
}
}).finally(function() {
$scope.$broadcast("scroll.infiniteScrollComplete");
});
};
})
template:
<ion-view view-title="News">
<ion-content>
<ion-refresher on-refresh="Reload()"></ion-refresher>
<div class="list">
<a collection-repeat="news in items" href="#/app/newsreader/{{news.id}}" class="item item-thumbnail-left">
<h2>{{news.headline}}</h2>
<div class="item-text-wrap" ng-bind-html="news.teaser"></div>
</a>
</div>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>
</ion-content>
</ion-view>
How can I resolve this?
Just found the solution on my own.
.controller('NewsCtrl', function($scope, newsDataService) {
$scope.items =[]
$scope.page = 1;
newsDataService.GetPosts().then(function(items){
$scope.items = items.data.response;
});
$scope.Reload = function() {
console.log('reload');
$scope.items =[];
$scope.page = 1;
$scope.loadMore();
};
$scope.loadMore = function(argument) {
$scope.page++;
newsDataService.GetMorePosts($scope.page).then(function(items){
if (items.data.response) {
$scope.items = $scope.items.concat(items.data.response);
$scope.noMoreItemsAvailable = false;
} else {
$scope.noMoreItemsAvailable = true;
}
}).finally(function() {
$scope.$broadcast("scroll.infiniteScrollComplete");
$scope.$broadcast('scroll.refreshComplete');
});
};
})

Vimeo drop uploader to click uploader

im using vimeo drop uploader on my site. i got the uploder from
https://github.com/websemantics/vimeo-upload
its working well when i drop the image. but i dont know how to on click to open uploder window..
the uploder dont have the file input its only have the div
this is html
<div class="progress">
<div id="progress" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="46" aria-valuemin="0" aria-valuemax="100" style="width: 0%">0%
</div>
</div>
<div id="drop_zone">Drop files here</div>
and they use this script
<script>
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
var accessToken = document.getElementById("accessToken").value;
var upgrade_to_1080 = document.getElementById("upgrade_to_1080").checked;
// Set Video Data
var videoName = document.getElementById("videoName").value;
var videoDescription = document.getElementById("videoDescription").value;
// Clear the results div
var node = document.getElementById('results');
while (node.hasChildNodes()) node.removeChild(node.firstChild);
// Rest the progress bar
updateProgress(0);
var uploader = new MediaUploader({
file: files[0],
token: accessToken,
upgrade_to_1080: upgrade_to_1080,
videoData: {
name: (videoName > '') ? videoName : 'Default name',
description: (videoDescription > '') ? videoDescription : 'Default description'
},
onError: function(data) {
var errorResponse = JSON.parse(data);
message = errorResponse.error;
var element = document.createElement("div");
element.setAttribute('class', "alert alert-danger");
element.appendChild(document.createTextNode(message));
document.getElementById('results1').appendChild(element);
},
onProgress: function(data) {
updateProgress(data.loaded / data.total);
},
onComplete: function(videoId) {
var url = "https://vimeo.com/"+videoId;
document.getElementById("video").value = url;
//var a = document.createElement('a');
// a.appendChild(document.createTextNode(url));
// a.setAttribute('href',url);
//
// var element = document.createElement("div");
// element.setAttribute('class', "alert alert-success");
// element.appendChild(a);
//
// document.getElementById('results').appendChild(element);
}
});
uploader.upload();
}
/**
* Dragover handler to set the drop effect.
*/
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
/**
* Wire up drag & drop listeners once page loads
*/
document.addEventListener('DOMContentLoaded', function () {
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
});
var elem = document.getElementById('drop_zone');
if(elem && document.createEvent) {
var evt = document.createEvent("MouseEvents");
evt.initEvent("click", true, false);
elem.dispatchEvent(evt);
}
/**
* Updat progress bar.
*/
function updateProgress(progress) {
progress = Math.floor(progress * 100);
var element = document.getElementById('progress');
element.setAttribute('style', 'width:'+progress+'%');
element.innerHTML = progress+'%';
}
progress
</script>
Can you help me on this how to i upload an video on click..
Demo https://github.com/googledrive/cors-upload-sample
Thanks

Ionic Local storage put information into array

Here is the code
Controller.js
$scope.addFavorite = function (index) {
$scope.temp = {
id: index
};
$scope.dish = $localStorage.getObject('favorites', '{}');
console.log($localStorage.get('favorites'));
$localStorage.storeObject('favorites', JSON.stringify($scope.temp));
var favorites = $localStorage.getObject('favorites');
console.log(favorites);
favoriteFactory.addToFavorites(index);
$ionicListDelegate.closeOptionButtons();
}
Service.js
.factory('favoriteFactory', ['$resource', 'baseURL', function ($resource, baseURL) {
var favFac = {};
var favorites = [];
favFac.addToFavorites = function (index) {
for (var i = 0; i < favorites.length; i++) {
if (favorites[i].id == index)
return;
}
favorites.push({id: index});
};
favFac.deleteFromFavorites = function (index) {
for (var i = 0; i < favorites.length; i++) {
if (favorites[i].id == index) {
favorites.splice(i, 1);
}
}
}
favFac.getFavorites = function () {
return favorites;
};
return favFac;
}])
.factory('$localStorage', ['$window', function($window) {
return {
store: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
storeObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key,defaultValue) {
return JSON.parse($window.localStorage[key] || defaultValue);
}
}
}])
I want to make a Favorites function, and I want to put every item's ID that marked into an array.
But, it couldn't expand the array and only change the value.
Did I make something wrong on here? Or maybe I put a wrong method on here?
Thank you in advance!
I just create logic for storing object, you have to made logic for remove object from localstorage.
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script>document.write('<base href="' + document.location + '" />');</script>
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.9/angular.js" data-semver="1.4.9"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="item in items">
{{item.item_name}}
<button ng-click="addFavorite(item.id)">Add to Favorite</button>
<br><hr>
</div>
</body>
</html>
<script type="text/javascript">
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$http)
{
$scope.items = [
{id:1,item_name:'Apple'},
{id:2,item_name:'Banana'},
{id:3,item_name:'Grapes'},
]
$scope.addFavorite = function (index)
{
if(localStorage.getItem('favorites')!=undefined)
{
var old_favorite = JSON.parse(localStorage.getItem('favorites'));
var obj = {index:index};
old_favorite.push(obj);
localStorage.setItem('favorites',JSON.stringify(old_favorite));
}
else
{
var obj = [{index:index}];
localStorage.setItem('favorites',JSON.stringify(obj));
}
}
});
</script>

How can i render DOM object from angularjs?

I am making DOM object through javascript and i want it to render it through angularjs but it display like [object HTMLDivElement]
but in browser console its
but it renders like
.directive('attachmentify', [
function() {
return {
restrict: 'A',
scope: {
item: "#filename"
},
template: "<div ng-bind-html='content'></div>",
compile: function(iElement, iAttrs) {
return function($scope, element, attr) {
var file = $scope.item;
// console.log
// $scope.file =file;
}
},
controller: function($scope) {
var img = ['jpg', 'jpeg', 'png'];
var c = 0;
img.forEach(function(element, index) {
if ($scope.item.endsWith(element)) c++;
});
if (c) {
var div = document.createElement('div');
div.setAttribute('name', 'samundra')
div.innerHTML = "ram"
} else {
var div = document.createElement('div');
div.setAttribute('name', 'ramundra')
div.innerHTML = "sam"
}
$scope.content = div;
console.log(div);
}
}
}
])
In your controller instead of assign DOM element instance, You can set $scope.content to html
$scope.content="<div name='ramundra'>ram></div>";

alert() message isn't being called in my form

Firebug is giving me no error messages, but it's not working. The idea is regardless of whether the user picks an option from dropdown or if they type in something in search box, I want the alert() message defined below to alert what the value of the variable result is (e.g. {filter: Germany}). And it doesn't. I think the javascript breaks down right when a new Form instance is instantiated because I tried putting an alert in the Form variable and it was never triggered. Note that everything that pertains to this issue occurs when form.calculation() is called.
markup:
<fieldset>
<select name="filter" alter-data="dropFilter">
<option>Germany</option>
<option>Ukraine</option>
<option>Estonia</option>
</select>
<input type="text" alter-data="searchFilter" />
</fieldset>
javascript (below the body tag)
<script>
(function($){
var listview = $('#listview');
var lists = (function(){
var criteria = {
dropFilter: {
insert: function(value){
if(value)
return handleFilter("filter", value);
},
msg: "Filtering..."
},
searchFilter: {
insert: function(value){
if(value)
return handleFilter("search", value);
},
msg: "Searching..."
}
}
var handleFilter = function(key,value){
return {key: value};
}
return {
create: function(component){
var component = component.href.substring(component.href.lastIndexOf('#') + 1);
return component;
},
setDefaults: function(component){
var parameter = {};
switch(component){
case "sites":
parameter = {
'order': 'site_num',
'per_page': '20',
'url': 'sites'
}
}
return parameter;
},
getCriteria: function(criterion){
return criteria[criterion];
},
addCriteria: function(criterion, method){
criteria[criterion] = method;
}
}
})();
var Form = function(form){
var fields = [];
$(form[0].elements).each(function(){
var field = $(this);
if(typeof field.attr('alter-data') !== 'undefined') fields.push(new Field(field));
})
}
Form.prototype = {
initiate: function(){
for(field in this.fields){
this.fields[field].calculate();
}
},
isCalculable: function(){
for(field in this.fields){
if(!this.fields[field].alterData){
return false;
}
}
return true;
}
}
var Field = function(field){
this.field = field;
this.alterData = false;
this.attach("change");
this.attach("keyup");
}
Field.prototype = {
attach: function(event){
var obj = this;
if(event == "change"){
obj.field.bind("change", function(){
return obj.calculate();
})
}
if(event == "keyup"){
obj.field.bind("keyup", function(e){
return obj.calculate();
})
}
},
calculate: function(){
var obj = this,
field = obj.field,
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = field.attr("alter-data").split(" "),
container = field.parent(),
messages = [];
field.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
if(field.val()){
var result = criterion.insert(field.val());
container.addClass("waitingMsg");
messages.push(criterion.msg);
obj.alterData = true;
alert(result);
initializeTable(result);
}
else {
return false;
obj.alterData = false;
}
}
if(messages.length){
for(msg in messages){
msgList.append("<li>" + messages[msg] + "</li");
}
}
else{
msgList.remove();
}
}
}
$('#dashboard a').click(function(){
var currentComponent = lists.create(this);
var custom = lists.setDefaults(currentComponent);
initializeTable(custom);
});
var initializeTable = function(custom){
var defaults = {};
var custom = custom || {};
var query_string = $.extend(defaults, custom);
var params = [];
$.each(query_string, function(key,value){
params += key + ': ' + value;
})
var url = custom['url'];
$.ajax({
type: 'GET',
url: '/' + url,
data: params,
dataType: 'html',
error: function(){},
beforeSend: function(){},
complete: function() {},
success: function(response) {
listview.html(response);
}
})
}
$.extend($.fn, {
calculation: function(){
var formReady = new Form($(this));
if(formReady.isCalculable) {
formReady.initiate();
}
}
})
var form = $('fieldset');
form.calculation();
})(jQuery)
Thank you for anyone who responds. I spent a lot of time trying to make this work.
The initial problem as to why the alert() was not being triggered when Form is instantiated is because, as you can see, the elements property belongs to the Form object, not fieldset object. And as you can see in the html, I place the fields as descendents of the fieldset object, not form.