Return all json elements in JavaScript - javascript

I have some code I am trying to reverse engineer. Here is the script...
define(function (require) {
"use strict";
var $ = require('jquery'),
Handlebars = require('handlebars'),
groupAdapter = require('adapters/group'),
homeHtml = require('text!tpl/Home.html'),
groupListItemHtml = require('text!tpl/GroupList.html'),
homeTpl = Handlebars.compile(homeHtml),
groupListItemTpl = Handlebars.compile(groupListItemHtml);
return function () {
this.initialize = function () {
// Define a div wrapper for the view. The div wrapper is used to attach events.
this.$el = $('<div/>');
this.$el.on('keyup', '.search-key', this.findByName);
};
this.render = function () {
this.$el.html(homeTpl());
return this;
};
this.findByName = function () {
groupAdapter.findByName($('.search-key').val()).done(function (products) {
$('.product-list').html(groupListItemTpl(products));
});
};
this.initialize();
};
});
...here is the template that is being used in tpl/home.html
<div class="topcoat-navigation-bar">
<div class="topcoat-navigation-bar__item center full">
<h1 class="topcoat-navigation-bar__title">Daily Comedy App</h1>
</div>
</div>
<div class="search-bar">
<input type="search" placeholder="search" class="topcoat-search-input search-key">
</div>
<div class="topcoat-list__container scroller" style="top:138px;">
<ul class='topcoat-list list product-list '></ul>
</div>
So...the current functionality is that a search bar is displayed on the home page, and when text is typed data from my json is displayed on the page.
What I would like to do is simply loadd all the data from my json on this initial page, rather than have the user search.
My JS stinks, so be kind! ;)
PS phonegap people might recognise this code from the EU Day.

Related

using javascript libraries don't work on webpage when loading data from json file

I created a javascript code to create grid and populate it with cards, using data from json file, and load them into a web page.
This is the code:
// load data into grid container
const container = document.querySelector(".grid");
// get data from the file, using loadData(), inside it populateContainer
function loadData() {
const request = new XMLHttpRequest();
request.open("get", "data.json");
request.onload = () => {
try {
const json = JSON.parse(request.responseText);
populateContainer(json);
} catch (e) {
console.warn("error");
}
};
request.send();
}
function populateContainer(json) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
json.forEach((row) => {
const card = document.createElement("div");
card.setAttribute("class", `grid-item ${row[7]}`);
card.setAttribute("data-category", `${row[7]}`);
// header
let header = document.createElement("div");
header.setAttribute("class", "card-header");
header.innerHTML = `Current = ${row[1]}$ Original Price = ${row[2]}$ / Discount = ${row[3]}%`;
card.appendChild(header);
// pic
let img = document.createElement("img");
img.setAttribute("class", "card-image");
img.src = `https://${row[6]}`;
card.appendChild(img);
// BODY
let cardBody = document.createElement("div");
cardBody.setAttribute("class", "card-content");
card.appendChild(cardBody);
// -->Title + link
let cardTitle = document.createElement("h4");
cardTitle.setAttribute("class", "card-title");
cardTitle.innerHTML = `<a href='https://${row[4]}'>${row[0]}</a>`;
cardBody.appendChild(cardTitle);
container.appendChild(card);
});
}
document.addEventListener("DOMContentLoaded", () => {
loadData();
});
This is the html body (the javascript script is in main.js file):
<body>
<div id="filters" class=".filter-button-group button-group">
<div class="button All">show all</div>
<div class="button HomeGarden">Home & Garden</div>
<div class="button Electronics">Electronics</div>
<div class="button MomKids">Mom & Kids</div>
<div class="button SportsOutdoor">Sports & Outdoor</div>
<div class="button Accessories">Accessories</div>
<div class="button HealthBeauty">Health & Beauty</div>
</div>
<div class="grid">
</div>
<script src="main.js"></script>
</body>
The code work well, and it create the grid and elements inside it,
but when I want to add a filter for those cards by category, using library like https://listjs.com or https://isotope.metafizzy.co it doesnt work.
How I can apply the filter to my code ?
What issues exactly did occur when trying to filter?
Here is a technical cut-through on how to get your script working by the following steps:
Include Isotope (as a script-tag,using the download-link)
Add "data-filter" attributes in HTML (I added three of them as an example):
<div class="button Electronics" data-filter="[data-category='Electronics']">
Initialize Isotope:
$grid = new Isotope( '.grid',{
itemSelector: '.grid-item',
layoutMode: 'fitRows',
});
Whenever you want to filter, filter. I bound your links to the .arrange-fn using JQuery, but feel free to do it some other way:
$('#filters').on( 'click', 'div.button', function() {
var filterValue = $( this ).attr('data-filter');
$grid.arrange({ filter: filterValue });
});
Did you get any issues trying to do so? I mocked your JSON since I got no service returning it, but in case it's a timing issue, just put the initialization (see above) right below the container.appendChild(card);, that should make it work.
Feel free to ask if I didn't cover some aspect of your question.
Best wishes

Separating functions on angular

I'm developing a new proyect using angular and I have separated the: App (main module), controller and services in diferent files:
The responsabilities are:
indexApp.js
And them code is:
(function(indexApp) {
indexApp.App = {};
indexApp.Init = function() {
indexApp.App = angular.module("MainAppModule", ["MainControllerModule", "MainServiceModule"]);
};
}(window.indexApp = window.indexApp || {}));
indexController.js
And them code is:
(function (indexController) {
indexController.App = {};
indexController.MainController = function (service) {
var self = this;
var dataRetrieved = service.Login();
self.movie = {
title: dataRetrieved.Id,
director: dataRetrieved.Name,
date: dataRetrieved.LastName,
mpaa: "PG-13",
id: 0,
clickCommand: function () {
alert(self.movie.director);
},
loadData: function (id) {
console.log(id);
if (id !== 0) {
self.movie.title = "Titulo";
self.movie.director = "Director";
self.movie.date = "Mayo 16 de 2015";
self.movie.mpaa = "PG-25";
self.movie.id = id;
}
}
}
};
indexController.SetUrl = function (data) {
indexController.Redirect = data.Redirect;
};
indexController.Init = function () {
indexController.App = angular.module("MainControllerModule", []);
indexController.App.controller("MainController", indexController.MainController);
indexController.MainController.$inject = ["MainService"];
};
}(window.indexController = window.indexController || {}));
indexService.js
Them code is:
(function (indexService) {
indexService.App = {};
indexService.MainService = function () {
var self = this;
self.Login = function () {
return {
Id: 1,
Name: "Freddy",
LastName: "Castelblanco"
};
};
};
indexService.SetUrl = function (data) {
indexService.Login = data.Login;
};
indexService.Init = function () {
indexService.App = angular.module("MainServiceModule", []);
indexService.App.service("MainService", indexService.MainService);
};
}(window.indexService = window.indexService || {}));
At the end in my view I call the follow methods:
#using System.Web.Optimization
#{
Layout = "~/Views/Shared/_Layout.cshtml";
var id = 20;
}
<div ng-app="MainAppModule">
<div ng-controller="MainController as vm">
<div ng-init="vm.movie.loadData(#id)">
<div class="row">
<div class="col-md-12">{{vm.movie.title}}</div>
<input type="text" ng-model="vm.movie.title"><br>
</div>
<div class="row">
<div class="col-md-12">{{vm.movie.director}}</div>
</div>
<div class="row">
<div class="col-md-12">{{vm.movie.date}}</div>
</div>
<div class="row">
<div class="col-md-12">{{vm.movie.mpaa}}</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="button" ng-click="vm.movie.clickCommand()">Click me !!</button>
</div>
</div>
</div>
</div>
</div>
#section scripts
{
#Scripts.Render("~/bundles/index")
<script type="text/javascript">
indexApp.Init();
indexService.Init();
indexController.Init();
</script>
}
Is a correct way to use angular ?? Im using dependency injection.
How you define an angular app is up to you but angular provides modules to deal with code organization, prevent global scope pollution, dependency injection among other things
Angular apps don't have a main method. Instead modules declaratively specify how an application should be bootstrapped
You are using a common method found in other frameworks of using var self = this to add functionality to your app but angular comes with a nice gift scopes. Scopes are extremely useful because all angular apps have one and only one $rootScope wich you can use to store commonly used functionality all across your application. Also scope are organized in a hierarchy wich give you the abitity to nest scopes and make some logic work only on specific DOM elements.
Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events.
To glue your application you should use $watch on the scope to be notified of changes but usually you use any of the predefined directives that do this automatically for simple task like binding and changing attributes eg. ngBind, ngClick, etc.
Scope is the glue between application controller and the view. During the template linking phase the directives set up $watch expressions on the scope. The $watch allows the directives to be notified of property changes, which allows the directive to render the updated value to the DOM.
I personally don't use IIFE when I'm using angular but this is a personal choice. The iife allows you to prevent global scope pollution by wrapping variables inside a function scope so you don't have name collisions but angular introduces providers which can help you to create functionality using factories and services so basically you wrap all your functionality in one of them (read which is the most suitable for your task) and you have already included dependency injection in the mix for free.
Finally there are three ways to use dependency injection (or ways to anotate it).
Inline Array Annotation
mymodule.controller('MyController', ['$scope', function($scope) {
// your code
}]);
$inject Property Annotation
var MyController = function($scope) {
// ...
}
MyController.$inject = ['$scope'];
someModule.controller('MyController', MyController);
Implicit Annotation
someModule.controller('MyController', function($scope) {
// ...
});
You are free to use the way that you feel more confortable with but you should be aware that the last alternative is dangerous if you plan to minify your code because angular rely in variable names to find the dependencies and those will get renamed in the minification process. Personaly I use the first and it seems the most popular since you don't need the extra variable used in the second alternative.
Your code can be rewritten as follows
angular.module('services', []).service('MainService', function () {
return {
Login: function () {
return {
Id: 1,
Name: "Freddy",
LastName: "Castelblanco"
};
}
};
});
angular.module('controllers', []).controller('MainController', ['$scope', 'MainService', function ($scope, service) {
var dataRetrieved = service.Login();
$scope.movie = {
title: dataRetrieved.Id,
director: dataRetrieved.Name,
date: dataRetrieved.LastName,
mpaa: "PG-13",
id: 0
};
$scope.clickCommand = function () {
alert($scope.movie.director);
};
$scope.loadData = function (id) {
if (id !== 0) {
$scope.movie.title = "Titulo";
$scope.movie.director = "Director";
$scope.movie.date = "Mayo 16 de 2015";
$scope.movie.mpaa = "PG-25";
$scope.movie.id = id;
}
}
}]);
angular.module('MainAppModule', ['controllers', 'services']);
And your html
<div ng-app="MainAppModule">
<div ng-controller="MainController">
<div ng-init="loadData(#id)">
<div class="row">
<div class="col-md-12">{{movie.title}}</div>
<input type="text" ng-model="movie.title">
<br>
</div>
<div class="row">
<div class="col-md-12">{{movie.director}}</div>
</div>
<div class="row">
<div class="col-md-12">{{movie.date}}</div>
</div>
<div class="row">
<div class="col-md-12">{{movie.mpaa}}</div>
</div>
<div class="row">
<div class="col-md-12">
<button type="button" ng-click="clickCommand()">Click me !!</button>
</div>
</div>
</div>
</div>
</div>
{Update}
You can also check AngularJS: Understanding design pattern for guidelines on how you should structure your angular app

Component fails to display the contents of the array

I am new to knockout.js and am trying to create a simple notification message component. What's happening is that the binding appears to occur, but there are no updates happening to the UI. Below is the code, and I would appreciate any help in locating where this is falling down.
Please note: I am using ASP.NET MVC 5, Knockout.js 3.2.0, Require.js 2.1.14 with AMD for accessing scripts and views.
View - Hub
<div class="row">
<notification-hub></notification-hub>
</div>
<button type="button">Push Me!</button>
#section scripts {
<script src="~/Scripts/Views/Home/index.js" type="text/javascript"></script>
}
Hub Script
require(["ko", "jquery", "ViewModels/notificationMessage", "Components/Notifications/hub", "Plugins/jquery.timeago"], function (ko, jquery, notificationMessage, notificationHub) {
try {
// Register the component.
ko.components.register("notification-hub", {
viewModel: notificationHub,
template: { require: "text!/Components/Notifications/HubItemView" }
});
// Create an instance of the hub and add an inital message.
var hub = new notificationHub();
hub.addMessage(new notificationMessage("Test", "This is a test message.", "2015-02-06 11:00 AM"));
// Bind things up.
ko.applyBindings(hub, $("notification-hub")[0]);
// Create a handler for the button click.
$("button").on("click", function () {
hub.addMessage(new notificationMessage("New Message", "This is a new message", new Date().toLocaleDateString()));
});
}
catch (e) {
$("#displayValues").html("Something went wrong...");
Debug.writeln("Script error: " + e.message);
}
});
ViewModel - Hub
define(["ko", "jquery"], function (ko, jquery) {
// Create the hub's main ViewModel.
function notificationHub() {
var self = this;
// Define the Properties.
self.messages = ko.observableArray();
self.count = ko.computed(function () { return self.messages().length; });
}
// Define the addMessage method.
notificationHub.prototype.addMessage = function (msg) {
var self = this;
// Pop message to the top of the stack.
self.messages().push(msg);
Debug.writeln("Count of message array: " + self.messages().length);
}
return notificationHub;
});
View - Message Model
<p data-bind="if: messages().length == 0">Unfortunately we didn't find any records.</p>
<ul data-bind="foreach: messages">
<li class="notificationMessage">
<span class="timeAgo" data-bind="text: createdDate"></span>
<h2 data-bind="text: title"></h2>
<p data-bind="text: message"></p>
</li>
</ul>
<!-- For debugging purposes -->
<input type="text" data-bind="value: count" />
ViewModel - Message Model
define(["ko"], function (ko) {
// Define the ViewModel for the messages themselves.
return function notificationMessage(title, message, date) {
var self = this;
// Define the Properties.
self.title = title;
self.message = message;
self.createdDate = date;
};
});

Asp.Net Mvc Render Partial View With Knockout

I use Web Api and Knockout.js in my project. I want to try like this: if I click the "Home" I want to refresh just main div. So I write this code.
My script in layout.cshtml
<script type="text/javascript">
$(document).ready(function () {
ko.applyBindings(new TalesViewModel());//First load the code is runnig and load the main div
function TalesViewModel() {
var self = this;
self.tales = ko.observableArray();
$.getJSON("/api/tales/", self.tales);
}
$('#home').click(function () {
var Tale = function (TaleName, Content, VoicePath, Tales) {
self = this;
self.TaleName = TaleName;
self.Content = Content;
self.VoicePath = VoicePath;
}
var mapping = {
'tales': {
create: function (options) {
return new Tale(options.data.TaleName, options.data.Content,
options.data.VoicePath);
}
}
}
var data = $.getJSON("/api/tales/", Tale);
var viewModel = ko.mapping.fromjs(data, mapping);
ko.applyBindings(viewModel);
})
})
</script>
I want to refresh this place
<div id="main">
#RenderBody()
</div>
TaleList.cshtml (PartialView)
<div>
<ul data-bind="foreach: tales">
<li>
<div>
<div>Masal Adı</div>
<span data-bind="text: $data.TaleName"></span>
</div>
<div>
<div>İçerik</div>
<span data-bind="text: $data.Content"></span>
</div>
<div>
<div>Ses Dosyası</div>
<span data-bind="text: $data.VoicePath"></span>
</div>
</li>
</ul>
When I clicked Home main div is refresh but no data in here. I think I have to use Knockout something but I don't know how can I do it.
I hope I can explain. Thanks all replies.
Update
If I check with firebug I see this error "TypeError: Object # has no method 'fromjs'"
Update2
I added my first knockout code when I load the project.
This is what you need to do:
Create a js object
var Tale = function (TaleName, Content, VoicePath, Tales) {
self = this;
self.TaleName = TaleName;
self.Content = Content;
self.VoicePath = VoicePath;
}
Create a mapping to convert to your js objects
var mapping = {
'tales': {
create: function(options) {
return new Tale(options.data.TaleName, options.data.Content,
options.data.VoicePath);
}
}
}
Check that your data matches something like below, checking the names match as below:
var data = {"tales" : [{"TaleName": "T1", "Content":"c1", "VoicePath":"v1"}, {"TaleName": "T2", "Content":"c2", "VoicePath":"v2"}]}
var viewModel = ko.mapping.fromJS(data, mapping);
Apply the bindings
ko.applyBindings(viewModel);
Here is a working fiddle with mimicked data
http://jsfiddle.net/dxJpc/1/
Update
You are mixing a combination of getJson and ajax, you only need one.
This can be replaced: (With Ajax)
$.ajax({
type: 'GET',
url: '/Pages/TaleList/',
contentType: 'application/html; charset=utf-8',
dataType: 'html'
})
.success(function (data) {
alert("okey!")
var viewModel = ko.mapping.fromJS(data, mapping);
ko.applyBindings(viewModel);
})
.error(function (req, status, error) {
alert("Error!Occured")
})
With getJSON:
var data = $.getJSON("/api/tales/", Tale);
var viewModel = ko.mapping.fromJS(data, mapping);
ko.applyBindings(viewModel);
Update 3
If you are loading your initial load as you have changed it to, you can simply put this in your on click event:
$('#home').click(function () {
ko.applyBindings(new TalesViewModel());
})
Update 4
Declare the view model in the document ready.
$(document).ready(function () {
var viewModel = new TalesViewModel();
ko.applyBindings(viewModel);
Then change your click to this:
$(document).ready(function () {
viewModel = new TalesViewModel();

Ember.TextField : Access to jquery object

my first post on stackoverflow. (and english is not my native tongue).
I am trying to learn how to use emberjs.
It's not easy because of the lack of good tutorials.
So I decided to code a chat, I use nodejs and socket.io server-side.
Html
<script type="text/x-handlebars">
<div class="page">
<div class="users">
</div>
<div class="messagebox">
{{#view App.TextField valueBinding="currentMsg" placeholder="your message"}}{{/view}}
<button {{action "sendMsg"}}>Send</button>
</div>
<div id="chatbox">
{{#collection contentBinding="App.MsgsController" tagName="ul"}}
<b>{{value}}</b>
{{/collection}}
</div>
</div>
</script>
Javascript
var id;
var socketio = io.connect("127.0.0.1:8888");
socketio.on('id', function (data) {
id = data;
});
socketio.on("broadcast", function (data) {
if (id == data.id) {
return
}
App.MsgsController.addMsg(data.message);
});
socketio.on("own", function (data) {
App.MsgsController.addMsg(data.message);
});
App = Ember.Application.create();
App.Msg = Ember.Object.extend({
value: null
});
App.MsgsController = Ember.ArrayController.create({
content: [],
addMsg: function (value) {
var msg = App.Msg.create({
value: value
});
this.pushObject(msg);
}
});
App.TextField = Ember.TextField.extend({
insertNewline: function() {
this.get("controller").send("sendMsg");
}
});
App.ApplicationController = Ember.Controller.extend({
currentMsg: 't',
sendMsg: function () {
var currentMsg = this.get('currentMsg');
if(currentMsg) {
socketio.emit("message", { message: currentMsg, id: id});
this.set('currentMsg', '');
}
}
});
I want to focus App.TextField after the App.ApplicationController.sendMsg call.
I tried
App.TextField.$().focus()
but it seems that I can only use $() inside of its methods.
Someone can help me, please?
Edit :
Ok, I found the answer.
App.TextField is like "class", and the one on the view is an instance.
I must add an id in my view
{{#view App.TextField valueBinding="currentMsg" placeholder="your message" id="mytextfield"}}{{/view}}
and use jquery selector to access to the instance
$('#mytextfield').focus();
Use didInsertElement hook for the view to handle jquery methods.
http://emberjs.com/api/classes/Ember.View.html#event_didInsertElement

Categories

Resources