Search Results

Search found 94919 results on 3797 pages for 'new folder'.

Page 235/3797 | < Previous Page | 231 232 233 234 235 236 237 238 239 240 241 242  | Next Page >

  • Setting folder to be writable by apache/php in windows?

    - by Chris Sobolewski
    I have a local test server, and I am attempting to write a file with PHP. I am getting a message that the folder (../uploads/) does not exist or I do not have permission. My directory structure is D:\xampp\htdocs\website\ //<--root D:\xampp\htdocs\website\library //<--where script runs D:\xampp\htdocs\website\uploads //<--where I'd like to save I know on a *nix server, I can just chmod the permission to 0777. What do I need to set on my windows box to give apache the ability to write a file?

    Read the article

  • Élections américaines : le New-Jersey votera par mail suite à l'ouragan Sandy, très innovant ou très risqué ?

    Les chercheurs en sécurité ont quelques réserves vis à vis du système de vote par Email mis en place au New Jersey suite à l'ouragan Sandy. [IMG]http://resources1.news.com.au/images/2012/11/06/1226511/153101-new-jersey-email-vote.jpg[/IMG] La décision du New Jersey afin de permettre aux électeurs bloqués par la tempête de vote par E-mail lors de l'élection de mardi peut être une réponse innovante suite à une catastrophe naturelle. Mais les chercheurs en sécurité ont prévenu que cette décision sans précédent pourrait être le déclenchement d'une autre tempête mais cette fois ci d'ordre politique. Au cours du weekend, le gouverneur Kim Guadano a annoncé que les électeurs touchés par la tempête pourrait demander par E-mail un bulletin de vote, le re...

    Read the article

  • Automatically sync a folder to a USB when USB is plugged in?

    - by John
    Is there a way to sync a folder to an USB drive when the drive is plugged in? I'd like it to sync, or copy over changes, both ways. I've seen the Back In Time and Unison-GTK applications, but I'd like for it to run as soon as the drive is mounted. What I mean is, unintrusively sync the two folders without any input from myself besides setting it up. If this isn't possible, is it possible to run the application when the thumb drive is plugged in to remind myself to sync manually? Thanks!

    Read the article

  • How do I suppress the "New release '12.10' available" message?

    - by cjm
    When I ssh into my Mythbuntu box, I get this message: Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-32-generic x86_64) * Documentation: https://help.ubuntu.com/ New release '12.10' available. Run 'do-release-upgrade' to upgrade to it. Last login: <redacted> $ But I don't intend to upgrade to 12.10, because Mythbuntu recommends using LTS releases only. How do I suppress the "New release '12.10' available" message? I don't want to be notified until the next LTS release is available. I've already gone to Update Manager Settings Updates and selected "Notify me of a new Ubuntu version: For long-term support versions", but that didn't get rid of this message.

    Read the article

  • Don’t Like New Google Search Interface? Switch To Old Interface

    - by Gopinath
    Google recently adopted a new user interface layout for it’s search engine. The new layout is very different to classic one, it provides many options on the left side to choose for enhanced search operations. Even though many users like this new interface, there are few who are more comfortable with the classic interface. If you are one among those who wanted to switch back to classic interface, you can access it by using the following http://www.google.com/webhp?hl=all Join us on Facebook to read all our stories right inside your Facebook news feed.

    Read the article

  • Tension between the dependency inversion principle and avoiding "new" in C++?

    - by Kazark
    I have seen a lot of advice that it is better to do Type object; than Type* object = new Type(); in C++ whenever possible. I understand the rational behind this and appreciate it. But according to my understanding, to practice dependency inversion requires pointers, e.g.: Type* object = new Implementation();. (Or am I wrong about that?) Is there an inherent tension between the DIP and avoiding new when using C++? If so, what patterns/principles/practices can be used to mitigate this tension?

    Read the article

  • In Subversion, how should I set up a new major version of my application?

    - by Steve McLeod
    I'm about to start work on a new version (version 4) of my commercial application. I use Subversion. Based on your experiences, mistakes, and successes, how would you recommend I set up the new version in Subversion? Here's some info: I intend to keep releasing critical updates in version 3 for some time after version 4 is released. However all development of new features will be solely in version 4. In case it is relevant: I'm a solo developer on this product, and that is likely to remain the case.

    Read the article

  • How to use database to generate multiple folder content page? [migrated]

    - by VenomVipes
    Scenario :I am trying to build a Mobile Entertainment Portal. It will enable users to download Music & Movies to their Cell Phones... Problem Exp : Suppose I upload 100 folders of Songs, each folder is for one Album. I want a way to generate a page with all the folders name (Album Name) in it. If user click on the page, they should be taken to a page where they get list of all songs in the album. Clicking on any song name will let them download it. Can it be done anyway or will I have to manually design each of the 3 pages for each album. If I do that, its time consuming and also will be difficult to change anything like footer, header...

    Read the article

  • Bad links point to old domain - should I disavow on new domain?

    - by user32573
    I am working with a site which we'll call www.newdomain.com, which was hit by Penguin this month despite no unusual practices. I found lots of really spammy links to their old site, www.olddomain.com, which 301s to the new domain. So I've gone through the process of identifying which links are really bad, made contact to ask for removal, and am at the stage of disavowing links. But wait! None of the bad links point to newdomain.com, and I worry that a disavow request via this domain in Webmaster Tools will damage something. Do the old band links affect the new site? If so, where do I disavow those old bad links? On Webmaster Tools for the new domain?

    Read the article

  • How do I move my LVM 250 GB root partition to a new 120GB hard disk?

    - by Dennis Schma
    I have the following situation: My current Ubuntu installation is running from an external HDD (250 GB) because I was to lazy to buy an new internal hdd. Now i've got a new internal (120GB) and i want to move everything to the internal. Installing Ubuntu new is out of disscussion because its to peronalized. Luckily (i hope so) the root partition is partitioned with LVM, so i hope i can move the partition to the smaller internal HDD. Is this possible? And where do i find help?

    Read the article

  • In terms of SEO, is it better to have a URL broken down by folder, or with dashed names?

    - by VictorKilo
    I am creating a friendly url interpreter for my website. I have read dozens of similar topics on this site, but none that seem to address my particular situation. What I want to know is if it's better to have: A well broken down URL where each category is represented by a folder domain.com/1036/OR/Lane/Lowell/Wetleau-Subdivision -OR- A URL which groups all of the categories and terms together domain.com/1036/Wetleau-Subdivision-Lowell-OR-Lane I am asking only in terms of what is best for SEO, not necessarily human readability. My thinking is that it may be better to group them all together like they are in the second example. My reasoning being that all of those terms represent the page and are more likely to draw a result. I am a complete SEO nub though, and I crave some expert guidance. Thank you in advance for any help given.

    Read the article

  • How to create website shortcuts on the desktop / in a folder using Chrome?

    - by it's me
    Help with something really basic, which I am unable to figure out. In Windows creating a shortcut (link) for a website is as easy as dragging-and-dropping the favicon/address bar to the desktop or a folder. I tried the same in Ubuntu (Chrome browser), but it's not working. The web page is being saved as a file, but not as a link/shortcut. Am I missing something or is there no way to quickly create shortcuts to web pages/web sites without installing some app for that? If the above is true, is there an app that does what I need? I hope I am clear enough.

    Read the article

  • Where are my Hard Drives/Local Disks on the COMPUTER/System Folder in Ubuntu 12.04?

    - by Russel
    Being first to try Ubuntu. But Where are my Hard Drives/Local Disks on the COMPUTER/System Folder in Ubuntu 12.04?! Before installing 12.04 i had tried the Ubuntu 10.10 Version Live and it was perfect in showing my Local Disks. But it couldn't recognize my GTX 470 Graphics driver so i thought of trying the recent version i.e 12.04. Fortunately it solved the Graphics driver thing but now i am stuck with finding My Local Disks on 12.04. I am sorry if this is a silly question, but i know nothing of Ubuntu at the moment. Regards,

    Read the article

  • How do I forward/redirect a website from a folder in a subdomain to another server?

    - by dozza
    I have a client with a site at: subdomain.theirdomain.com/folder It's a 50Gb gallery site that i've now cloned and have locally in MAMP. Once i've made some changes to it I need to host it at alternative physical server/hosting (I intend using a dedicated server I have access to with a technical domain name currently). However, the client would ideally like to keep the existing URL as it has been used extensively in marketing. I've done HTTP redirects and forwards and 301 redirects in the past, but I'm not sure how or even if I can do what the client wants. How can I achieve this, possibly using .htaccess and DNS entries? Caveats: I can't have the site at a 3rd party domain and the client isn't able/allowed to register any additional domains:

    Read the article

  • Why are new pages not being indexed and old pages stay in the index?

    - by ZakGottlieb
    I currently have a site that was recently restructured, causing much of its content to be reposted, creating new URL's for each page. To avoid duplicates, all of the existing pages were added to the robots file. That said, it has now been over a week - I know Google has recrawled the site - and when I search for term X, it is stil the old page that is ranking, with the new one nowhere to be seen. I'm assuming it's a cached version, but why are so many of the old pages still appearing in the index? Furthermore, all "tags" pages (it's a Q&A site, like this one) were also added to the robots a few months ago, yet I think they are all still appearing in the index. Anyone got any ideas about why this is happening, and how I can get my new pages indexed?

    Read the article

  • If C-Panel Indexing Manager sets a folder to "No Indexing" can it be crawled by a webcrawler?

    - by Graham
    People are able to view directories / folders on my site right now. So, they could go to mysite.com/images and see the full index. To prevent this, C-Panel offers an option to set a directory / folder to "No Indexing" under the "Index Manager." Will this option allow webcrawlers to crawl / index the images? Or, is there a simpler alternative to block access to all folders directly while still having it SEO friendly? My old server restricted direct access to folders by default. But, the new one does not. Any ideas on this? Thanks!

    Read the article

  • Is it possible to grant access to a folder in a SVN server using SVN's API?

    - by Splendonia
    I need to develop a web application (Using any language but I'm familiar with Frameworks Symfony2 and Rails), that is able to grant access to a user to a determined folder on another server on the same network from the application's front-end. I found out that SVN has an API and that I could interact with it with PHP or Ruby (Apparently), although I would be willing to program the application on another language, the server where the files are stored is using Windows and I thought on using Virtual SVN server, however I can't find any function on the API to grant users access to files and/or folders or access of any kind, like you usually do using the GUI (VirtualSVN on Windows). Am I missing anything? Is this even possible?

    Read the article

  • How to backup a dev & QA folder website structure?

    - by novicePrgrmr
    A site I just became in charge of uses a really simple two folder structure to host the dev site and the QA site. The sites are hosted on the company servers so I just have the sites' folders mapped on my desktop. I would like to run some kind of backup scheme, but I am finding it hard to think of a way to do this effectively. The problem is that we aren't using any revision control software, and since the servers aren't controlled by me, I don't think I will be able to implement anything like that. Or could I? The entire site is static too, so no DB's or anything besides html, images, PDFs, etc.

    Read the article

  • Need to add 30K new pages to a 10K page website - troubles ahead? (SEO)

    - by Jurga
    We have a situation with a website where we plan to add a huge amount of new pages. The domain is over 10 years old, approximately 10 thousand indexed pages, and the planned addition is approx. 30K new pages. Any idea how we should go about it? Must we schedule a gradual data release? Have you heard of any industry standards as to how many new pages per day / week / month should be added in order to appear natural and not get in trouble with Google? I.e. should we plan a bi-weekly addition of 5K?

    Read the article

  • [Google Maps] Trouble with invalid argument when switching jQueryUI based tabs

    - by Chad
    Here's a page with the issue To reproduce the error, using IE - click the directions tab, then any of the others. What I'm trying to do is this: On page load, do nothing really. However, when the directions tab loads - setup the map. Like so: $('#tabs').bind('tabsshow', function(event, ui) { if (ui.panel.id == "tabs-5") { // get map for directions var dirMap = new GMap2($("div#dirMap").get(0)); dirMap.setCenter(new GLatLng(35.79648921414565,139.40663874149323), 12); dirMap.enableScrollWheelZoom(); dirMap.addControl(new PanoMapTypeControl()); geocoder = new GClientGeocoder(); $("#dirMap").resizable({ stop: function() { dirMap.checkResize(); } }); // clear dirText $("div#dirMapText").html(""); dirMap.clearOverlays(); var polygon = new GPolygon([new GLatLng(35.724496338474104,139.3444061279297),new GLatLng(35.74748750802863,139.3363380432129),new GLatLng(35.75765724051559,139.34303283691406),new GLatLng(35.76545779822543,139.3418312072754),new GLatLng(35.767547103447725,139.3476676940918),new GLatLng(35.75835374997911,139.34955596923828),new GLatLng(35.755149755962755,139.3567657470703),new GLatLng(35.74679090345495,139.35796737670898),new GLatLng(35.74762682821177,139.36294555664062),new GLatLng(35.744422402303826,139.36346054077148),new GLatLng(35.74860206266584,139.36946868896484),new GLatLng(35.735644401200986,139.36843872070312),new GLatLng(35.73843117306677,139.36174392700195),new GLatLng(35.73592308277646,139.3531608581543),new GLatLng(35.72686543236113,139.35298919677734),new GLatLng(35.724496338474104,139.3444061279297)], "#f33f00", 5, 1, "#ff0000", 0.2);dirMap.addOverlay(polygon); // load directions directions = new GDirections(dirMap, $("div#dirMapText").get(0)); directions.load("from: [email protected],139.37083393335342 to: Ruby [email protected],139.40663874149323"); } }); What the heck is causing the error? The IE javascript debugger claims the error lies in main.js, line 139 character 28. (the google maps api file). Which is this line: function zf(a,b){a=a.style;a.width=b.getWidthString();a.height=b.getHeightString()} Any ideas? Thanks in advance!

    Read the article

  • Migrating master-slave MySQL database servers to 2 new servers, any tips or suggestions?

    - by mmattax
    I'm setting up 2 new database servers that will be replacing a current master-slave setup. All boxes are running / will be running MySQL on RHEL. Our current naming conventions: db1 - master database db2 - slave (using MySQL replication) db01 - new master db02 - new slave We need to get db01 to be the new master with db02 as the new slave. What is the best way to migrate db1 and db2 to db01 and db02? db1 and db2 are running in a production setting and we need to minimize all downtime; db1 has roughly 30GB of data in the database. Any suggestions or tips on how to migrate to our new servers would be much appreciated.

    Read the article

  • Using PowerShell, in Active Direcotry, how would I change all the DNS A records that have a given IP to a new IP?

    - by djsumdog
    We've been moving data centers and I have a lot of old records that were not correctly but in DNS as CNAME records, but A records that have a direct IP (e.g. 192.168.100.n) and they're all moving to a new subnet (10.19.100.n). I just need to write a powershell script to change all those records. I found this site: http://www.indented.co.uk/index.php/2008/12/30/administering-microsoft-dns-in-powershell/ and from it I made this simple script: $dnsServer = "meldc2" $scope = New-Object Management.ManagementScope("\\$dnsServer\root\MicrosoftDNS") $path = New-Object Management.ManagementPath("MicrosoftDNS_Zone") $options = New-Object Management.ObjectGetOptions($Null,[System.TimeSpan]::MaxValue, $True) $ZoneClass= New-Object Management.ManagementClass($scope,$path,$options) $Zones = Get-WMIObject -Computer $dnsServer -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_Zone" $Zones | Get-Member foreach($Z in $Zones) { $Z | Select-Object Name,DsIntegrated,ZoneType,Reverse,Data } but that only gets me a listing of root zones. I don't understand how to iterate over all the entries in each of the zones. Also, all the examples I've seen involve adding new zones, but there aren't any examples I can find on modifying existing A records.

    Read the article

  • Can't delete folder and I am admin. "You need permission to perform this action. You require permission from..."

    - by Tony_Henrich
    I can't delete a certain folder in windows 7. It's not a system folder. It was created by an app. I get an error message "You need permission to perform this action. You require permission from Tony....". I am an admin and logged in as myself Tony. I have full ownership of the folder with full control permission. I rebooted the machine. I killed the app which created the folder. I am out of ideas. Why is Windows 7 not letting me delete the folder?

    Read the article

  • How to change the value of a JLabel in runtime?

    - by user365465
    I want to change the image a JLabel is viewing during runtime, but I keep getting NullPointerExceptions or nothing happens when I press the magic button that's supposed to do things. Is it even possible in Java? Here is my code in its entirety: import java.text.*; import javax.swing.text.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class Shell implements ActionListener, MenuKeyListener { JFrame frame; JWindow window; JButton PSubmit; JPanel pane1, pane2; JRadioButton R1, R2, R3; ButtonGroup PGroup; JTabbedPane layout; String result; String border = "Border.png"; String DF = "Frame.png"; String list []; Driver driver; public Shell() { driver = new Driver(); list = new String [6]; } public void setFrame() { frame = new JFrame("Pokemon Program 3 by Systems Ready"); frame.setSize(600, 600); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); frame.getContentPane().setLayout(new BorderLayout()); } public void frameLayout() { layout = new JTabbedPane(); JPanel pane1 = new JPanel(); JPanel pane2 = new JPanel(); JLabel label = new JLabel("Please choose the restrictions:"); JLabel imgLabel1 = new JLabel(new ImageIcon(border)); JLabel notiLabel1 = new JLabel("The Pokemon chosen with these restrictions are: "); JLabel notiLabel2 = new JLabel("'No Restrictions': No restrictions for the kind of Pokemon chosen based on species or items."); JLabel notiLabel3 = new JLabel("'Battle Revolution': All Pokemon must have unique items."); JLabel notiLabel4 = new JLabel("'Battle Tower': All Pokemon must have unique items, Uber and Event Legendaries banned."); JLabel label2 = new JLabel("Please choose possible Pokemon:"); pane1.add(label); pearlButtons(); pane1.add(R1); pane1.add(R2); pane1.add(R3); pane1.add(PSubmit); pane1.add(notiLabel2); pane1.add(notiLabel3); pane1.add(notiLabel4); pane1.add(imgLabel1); pane1.add(notiLabel1); JLabel pokeLabel1 = new JLabel(new ImageIcon(DF)); JLabel pokeLabel2 = new JLabel(new ImageIcon(DF)); JLabel pokeLabel3 = new JLabel(new ImageIcon(DF)); JLabel pokeLabel4 = new JLabel(new ImageIcon(DF)); JLabel pokeLabel5 = new JLabel(new ImageIcon(DF)); JLabel pokeLabel6 = new JLabel(new ImageIcon(DF)); pane1.add(pokeLabel1); pane1.add(pokeLabel2); pane1.add(pokeLabel3); pane1.add(pokeLabel4); pane1.add(pokeLabel5); pane1.add(pokeLabel6); pane2.add(label2); layout.add("Pearl Version", pane1); layout.add("SoulSilver Version", pane2); frame.add(layout); } public void pearlButtons() { PGroup = new ButtonGroup(); R1 = new JRadioButton("No Restrictions", true); R1.setActionCommand("N"); R1.setVisible(true); R2 = new JRadioButton("Battle Revolution"); R2.setActionCommand("BR"); R2.setVisible(true); R3 = new JRadioButton("Battle Tower"); R3.setActionCommand("B"); R3.setVisible(true); PGroup.add(R1); PGroup.add(R2); PGroup.add(R3); PSubmit = new JButton("Submit"); PSubmit.setActionCommand("pstart"); PSubmit.setVisible(true); PSubmit.addActionListener(this); } public void pearlProcessing() { //The "list" array has a bunch of string names that get .png affixed to them (and I named the image files as such when I name them) String file1 = list[0] + ".png"; String file2 = list[1] + ".png"; String file3 = list[2] + ".png"; String file4 = list[3] + ".png"; String file5 = list[4] + ".png"; String file6 = list[5] + ".png"; /*-------------------------------------------------------------------------------// This is where the method's supposed to go to change the image... I've tried pokeLabel = new JLabel(new ImageIcon(file1));, but that yields a NullPointerException. //-----------------------------------------------------------------------------------*/ } public static void main(String[] args) { Shell test = new Shell(); test.setFrame(); test.frameLayout(); test.frame.setVisible(true); } public void actionPerformed(ActionEvent e) { if ("pstart".equals(e.getActionCommand())) { result = PGroup.getSelection().getActionCommand(); if (result.equals("N")) { list = driver.Prandom(); pearlProcessing(); } else System.out.println("Not done yet! ;)"); } } public void menuKeyPressed(MenuKeyEvent e) { System.out.println("pressed"); } public void menuKeyReleased(MenuKeyEvent e) { System.out.println("menuKeyReleased"); } public void menuKeyTyped(MenuKeyEvent e) { System.out.println("menuKeyTyped"); } }

    Read the article

  • Metro: Creating an IndexedDbDataSource for WinJS

    - by Stephen.Walther
    The goal of this blog entry is to describe how you can create custom data sources which you can use with the controls in the WinJS library. In particular, I explain how you can create an IndexedDbDataSource which you can use to store and retrieve data from an IndexedDB database. If you want to skip ahead, and ignore all of the fascinating content in-between, I’ve included the complete code for the IndexedDbDataSource at the very bottom of this blog entry. What is IndexedDB? IndexedDB is a database in the browser. You can use the IndexedDB API with all modern browsers including Firefox, Chrome, and Internet Explorer 10. And, of course, you can use IndexedDB with Metro style apps written with JavaScript. If you need to persist data in a Metro style app written with JavaScript then IndexedDB is a good option. Each Metro app can only interact with its own IndexedDB databases. And, IndexedDB provides you with transactions, indices, and cursors – the elements of any modern database. An IndexedDB database might be different than the type of database that you normally use. An IndexedDB database is an object-oriented database and not a relational database. Instead of storing data in tables, you store data in object stores. You store JavaScript objects in an IndexedDB object store. You create new IndexedDB object stores by handling the upgradeneeded event when you attempt to open a connection to an IndexedDB database. For example, here’s how you would both open a connection to an existing database named TasksDB and create the TasksDB database when it does not already exist: var reqOpen = window.indexedDB.open(“TasksDB”, 2); reqOpen.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); }; reqOpen.onsuccess = function () { var db = reqOpen.result; // Do something with db }; When you call window.indexedDB.open(), and the database does not already exist, then the upgradeneeded event is raised. In the code above, the upgradeneeded handler creates a new object store named tasks. The new object store has an auto-increment column named id which acts as the primary key column. If the database already exists with the right version, and you call window.indexedDB.open(), then the success event is raised. At that point, you have an open connection to the existing database and you can start doing something with the database. You use asynchronous methods to interact with an IndexedDB database. For example, the following code illustrates how you would add a new object to the tasks object store: var transaction = db.transaction(“tasks”, “readwrite”); var reqAdd = transaction.objectStore(“tasks”).add({ name: “Feed the dog” }); reqAdd.onsuccess = function() { // Tasks added successfully }; The code above creates a new database transaction, adds a new task to the tasks object store, and handles the success event. If the new task gets added successfully then the success event is raised. Creating a WinJS IndexedDbDataSource The most powerful control in the WinJS library is the ListView control. This is the control that you use to display a collection of items. If you want to display data with a ListView control, you need to bind the control to a data source. The WinJS library includes two objects which you can use as a data source: the List object and the StorageDataSource object. The List object enables you to represent a JavaScript array as a data source and the StorageDataSource enables you to represent the file system as a data source. If you want to bind an IndexedDB database to a ListView then you have a choice. You can either dump the items from the IndexedDB database into a List object or you can create a custom data source. I explored the first approach in a previous blog entry. In this blog entry, I explain how you can create a custom IndexedDB data source. Implementing the IListDataSource Interface You create a custom data source by implementing the IListDataSource interface. This interface contains the contract for the methods which the ListView needs to interact with a data source. The easiest way to implement the IListDataSource interface is to derive a new object from the base VirtualizedDataSource object. The VirtualizedDataSource object requires a data adapter which implements the IListDataAdapter interface. Yes, because of the number of objects involved, this is a little confusing. Your code ends up looking something like this: var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); The code above is used to create a new class named IndexedDbDataSource which derives from the base VirtualizedDataSource class. In the constructor for the new class, the base class _baseDataSourceConstructor() method is called. A data adapter is passed to the _baseDataSourceConstructor() method. The code above creates a new method exposed by the IndexedDbDataSource named nuke(). The nuke() method deletes all of the objects from an object store. The code above also overrides a method named remove(). Our derived remove() method accepts any type of key and removes the matching item from the object store. Almost all of the work of creating a custom data source goes into building the data adapter class. The data adapter class implements the IListDataAdapter interface which contains the following methods: · change() · getCount() · insertAfter() · insertAtEnd() · insertAtStart() · insertBefore() · itemsFromDescription() · itemsFromEnd() · itemsFromIndex() · itemsFromKey() · itemsFromStart() · itemSignature() · moveAfter() · moveBefore() · moveToEnd() · moveToStart() · remove() · setNotificationHandler() · compareByIdentity Fortunately, you are not required to implement all of these methods. You only need to implement the methods that you actually need. In the case of the IndexedDbDataSource, I implemented the getCount(), itemsFromIndex(), insertAtEnd(), and remove() methods. If you are creating a read-only data source then you really only need to implement the getCount() and itemsFromIndex() methods. Implementing the getCount() Method The getCount() method returns the total number of items from the data source. So, if you are storing 10,000 items in an object store then this method would return the value 10,000. Here’s how I implemented the getCount() method: getCount: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore().then(function (store) { var reqCount = store.count(); reqCount.onerror = that._error; reqCount.onsuccess = function (evt) { complete(evt.target.result); }; }); }); } The first thing that you should notice is that the getCount() method returns a WinJS promise. This is a requirement. The getCount() method is asynchronous which is a good thing because all of the IndexedDB methods (at least the methods implemented in current browsers) are also asynchronous. The code above retrieves an object store and then uses the IndexedDB count() method to get a count of the items in the object store. The value is returned from the promise by calling complete(). Implementing the itemsFromIndex method When a ListView displays its items, it calls the itemsFromIndex() method. By default, it calls this method multiple times to get different ranges of items. Three parameters are passed to the itemsFromIndex() method: the requestIndex, countBefore, and countAfter parameters. The requestIndex indicates the index of the item from the database to show. The countBefore and countAfter parameters represent hints. These are integer values which represent the number of items before and after the requestIndex to retrieve. Again, these are only hints and you can return as many items before and after the request index as you please. Here’s how I implemented the itemsFromIndex method: itemsFromIndex: function (requestIndex, countBefore, countAfter) { var that = this; return new WinJS.Promise(function (complete, error) { that.getCount().then(function (count) { if (requestIndex >= count) { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); } var startIndex = Math.max(0, requestIndex - countBefore); var endIndex = Math.min(count, requestIndex + countAfter + 1); that._getObjectStore().then(function (store) { var index = 0; var items = []; var req = store.openCursor(); req.onerror = that._error; req.onsuccess = function (evt) { var cursor = evt.target.result; if (index < startIndex) { index = startIndex; cursor.advance(startIndex); return; } if (cursor && index < endIndex) { index++; items.push({ key: cursor.value[store.keyPath].toString(), data: cursor.value }); cursor.continue(); return; } results = { items: items, offset: requestIndex - startIndex, totalCount: count }; complete(results); }; }); }); }); } In the code above, a cursor is used to iterate through the objects in an object store. You fetch the next item in the cursor by calling either the cursor.continue() or cursor.advance() method. The continue() method moves forward by one object and the advance() method moves forward a specified number of objects. Each time you call continue() or advance(), the success event is raised again. If the cursor is null then you know that you have reached the end of the cursor and you can return the results. Some things to be careful about here. First, the return value from the itemsFromIndex() method must implement the IFetchResult interface. In particular, you must return an object which has an items, offset, and totalCount property. Second, each item in the items array must implement the IListItem interface. Each item should have a key and a data property. Implementing the insertAtEnd() Method When creating the IndexedDbDataSource, I wanted to go beyond creating a simple read-only data source and support inserting and deleting objects. If you want to support adding new items with your data source then you need to implement the insertAtEnd() method. Here’s how I implemented the insertAtEnd() method for the IndexedDbDataSource: insertAtEnd:function(unused, data) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function(store) { var reqAdd = store.add(data); reqAdd.onerror = that._error; reqAdd.onsuccess = function (evt) { var reqGet = store.get(evt.target.result); reqGet.onerror = that._error; reqGet.onsuccess = function (evt) { var newItem = { key:evt.target.result[store.keyPath].toString(), data:evt.target.result } complete(newItem); }; }; }); }); } When implementing the insertAtEnd() method, you need to be careful to return an object which implements the IItem interface. In particular, you should return an object that has a key and a data property. The key must be a string and it uniquely represents the new item added to the data source. The value of the data property represents the new item itself. Implementing the remove() Method Finally, you use the remove() method to remove an item from the data source. You call the remove() method with the key of the item which you want to remove. Implementing the remove() method in the case of the IndexedDbDataSource was a little tricky. The problem is that an IndexedDB object store uses an integer key and the VirtualizedDataSource requires a string key. For that reason, I needed to override the remove() method in the derived IndexedDbDataSource class like this: var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); When you call remove(), you end up calling a method of the IndexedDbDataAdapter named removeInternal() . Here’s what the removeInternal() method looks like: setNotificationHandler: function (notificationHandler) { this._notificationHandler = notificationHandler; }, removeInternal: function(key) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqDelete = store.delete (key); reqDelete.onerror = that._error; reqDelete.onsuccess = function (evt) { that._notificationHandler.removed(key.toString()); complete(); }; }); }); } The removeInternal() method calls the IndexedDB delete() method to delete an item from the object store. If the item is deleted successfully then the _notificationHandler.remove() method is called. Because we are not implementing the standard IListDataAdapter remove() method, we need to notify the data source (and the ListView control bound to the data source) that an item has been removed. The way that you notify the data source is by calling the _notificationHandler.remove() method. Notice that we get the _notificationHandler in the code above by implementing another method in the IListDataAdapter interface: the setNotificationHandler() method. You can raise the following types of notifications using the _notificationHandler: · beginNotifications() · changed() · endNotifications() · inserted() · invalidateAll() · moved() · removed() · reload() These methods are all part of the IListDataNotificationHandler interface in the WinJS library. Implementing the nuke() Method I wanted to implement a method which would remove all of the items from an object store. Therefore, I created a method named nuke() which calls the IndexedDB clear() method: nuke: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqClear = store.clear(); reqClear.onerror = that._error; reqClear.onsuccess = function (evt) { that._notificationHandler.reload(); complete(); }; }); }); } Notice that the nuke() method calls the _notificationHandler.reload() method to notify the ListView to reload all of the items from its data source. Because we are implementing a custom method here, we need to use the _notificationHandler to send an update. Using the IndexedDbDataSource To illustrate how you can use the IndexedDbDataSource, I created a simple task list app. You can add new tasks, delete existing tasks, and nuke all of the tasks. You delete an item by selecting an item (swipe or right-click) and clicking the Delete button. Here’s the HTML page which contains the ListView, the form for adding new tasks, and the buttons for deleting and nuking tasks: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>DataSources</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.1.0.RC/css/ui-dark.css" rel="stylesheet" /> <script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script> <script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script> <!-- DataSources references --> <link href="indexedDb.css" rel="stylesheet" /> <script type="text/javascript" src="indexedDbDataSource.js"></script> <script src="indexedDb.js"></script> </head> <body> <div id="tmplTask" data-win-control="WinJS.Binding.Template"> <div class="taskItem"> Id: <span data-win-bind="innerText:id"></span> <br /><br /> Name: <span data-win-bind="innerText:name"></span> </div> </div> <div id="lvTasks" data-win-control="WinJS.UI.ListView" data-win-options="{ itemTemplate: select('#tmplTask'), selectionMode: 'single' }"></div> <form id="frmAdd"> <fieldset> <legend>Add Task</legend> <label>New Task</label> <input id="inputTaskName" required /> <button>Add</button> </fieldset> </form> <button id="btnNuke">Nuke</button> <button id="btnDelete">Delete</button> </body> </html> And here is the JavaScript code for the TaskList app: /// <reference path="//Microsoft.WinJS.1.0.RC/js/base.js" /> /// <reference path="//Microsoft.WinJS.1.0.RC/js/ui.js" /> function init() { WinJS.UI.processAll().done(function () { var lvTasks = document.getElementById("lvTasks").winControl; // Bind the ListView to its data source var tasksDataSource = new DataSources.IndexedDbDataSource("TasksDB", 1, "tasks", upgrade); lvTasks.itemDataSource = tasksDataSource; // Wire-up Add, Delete, Nuke buttons document.getElementById("frmAdd").addEventListener("submit", function (evt) { evt.preventDefault(); tasksDataSource.beginEdits(); tasksDataSource.insertAtEnd(null, { name: document.getElementById("inputTaskName").value }).done(function (newItem) { tasksDataSource.endEdits(); document.getElementById("frmAdd").reset(); lvTasks.ensureVisible(newItem.index); }); }); document.getElementById("btnDelete").addEventListener("click", function () { if (lvTasks.selection.count() == 1) { lvTasks.selection.getItems().done(function (items) { tasksDataSource.remove(items[0].data.id); }); } }); document.getElementById("btnNuke").addEventListener("click", function () { tasksDataSource.nuke(); }); // This method is called to initialize the IndexedDb database function upgrade(evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); } }); } document.addEventListener("DOMContentLoaded", init); The IndexedDbDataSource is created and bound to the ListView control with the following two lines of code: var tasksDataSource = new DataSources.IndexedDbDataSource("TasksDB", 1, "tasks", upgrade); lvTasks.itemDataSource = tasksDataSource; The IndexedDbDataSource is created with four parameters: the name of the database to create, the version of the database to create, the name of the object store to create, and a function which contains code to initialize the new database. The upgrade function creates a new object store named tasks with an auto-increment property named id: function upgrade(evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true }); } The Complete Code for the IndexedDbDataSource Here’s the complete code for the IndexedDbDataSource: (function () { /************************************************ * The IndexedDBDataAdapter enables you to work * with a HTML5 IndexedDB database. *************************************************/ var IndexedDbDataAdapter = WinJS.Class.define( function (dbName, dbVersion, objectStoreName, upgrade, error) { this._dbName = dbName; // database name this._dbVersion = dbVersion; // database version this._objectStoreName = objectStoreName; // object store name this._upgrade = upgrade; // database upgrade script this._error = error || function (evt) { console.log(evt.message); }; }, { /******************************************* * IListDataAdapter Interface Methods ********************************************/ getCount: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore().then(function (store) { var reqCount = store.count(); reqCount.onerror = that._error; reqCount.onsuccess = function (evt) { complete(evt.target.result); }; }); }); }, itemsFromIndex: function (requestIndex, countBefore, countAfter) { var that = this; return new WinJS.Promise(function (complete, error) { that.getCount().then(function (count) { if (requestIndex >= count) { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); } var startIndex = Math.max(0, requestIndex - countBefore); var endIndex = Math.min(count, requestIndex + countAfter + 1); that._getObjectStore().then(function (store) { var index = 0; var items = []; var req = store.openCursor(); req.onerror = that._error; req.onsuccess = function (evt) { var cursor = evt.target.result; if (index < startIndex) { index = startIndex; cursor.advance(startIndex); return; } if (cursor && index < endIndex) { index++; items.push({ key: cursor.value[store.keyPath].toString(), data: cursor.value }); cursor.continue(); return; } results = { items: items, offset: requestIndex - startIndex, totalCount: count }; complete(results); }; }); }); }); }, insertAtEnd:function(unused, data) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function(store) { var reqAdd = store.add(data); reqAdd.onerror = that._error; reqAdd.onsuccess = function (evt) { var reqGet = store.get(evt.target.result); reqGet.onerror = that._error; reqGet.onsuccess = function (evt) { var newItem = { key:evt.target.result[store.keyPath].toString(), data:evt.target.result } complete(newItem); }; }; }); }); }, setNotificationHandler: function (notificationHandler) { this._notificationHandler = notificationHandler; }, /***************************************** * IndexedDbDataSource Method ******************************************/ removeInternal: function(key) { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqDelete = store.delete (key); reqDelete.onerror = that._error; reqDelete.onsuccess = function (evt) { that._notificationHandler.removed(key.toString()); complete(); }; }); }); }, nuke: function () { var that = this; return new WinJS.Promise(function (complete, error) { that._getObjectStore("readwrite").done(function (store) { var reqClear = store.clear(); reqClear.onerror = that._error; reqClear.onsuccess = function (evt) { that._notificationHandler.reload(); complete(); }; }); }); }, /******************************************* * Private Methods ********************************************/ _ensureDbOpen: function () { var that = this; // Try to get cached Db if (that._cachedDb) { return WinJS.Promise.wrap(that._cachedDb); } // Otherwise, open the database return new WinJS.Promise(function (complete, error, progress) { var reqOpen = window.indexedDB.open(that._dbName, that._dbVersion); reqOpen.onerror = function (evt) { error(); }; reqOpen.onupgradeneeded = function (evt) { that._upgrade(evt); that._notificationHandler.invalidateAll(); }; reqOpen.onsuccess = function () { that._cachedDb = reqOpen.result; complete(that._cachedDb); }; }); }, _getObjectStore: function (type) { type = type || "readonly"; var that = this; return new WinJS.Promise(function (complete, error) { that._ensureDbOpen().then(function (db) { var transaction = db.transaction(that._objectStoreName, type); complete(transaction.objectStore(that._objectStoreName)); }); }); }, _get: function (key) { return new WinJS.Promise(function (complete, error) { that._getObjectStore().done(function (store) { var reqGet = store.get(key); reqGet.onerror = that._error; reqGet.onsuccess = function (item) { complete(item); }; }); }); } } ); var IndexedDbDataSource = WinJS.Class.derive( WinJS.UI.VirtualizedDataSource, function (dbName, dbVersion, objectStoreName, upgrade, error) { this._adapter = new IndexedDbDataAdapter(dbName, dbVersion, objectStoreName, upgrade, error); this._baseDataSourceConstructor(this._adapter); }, { nuke: function () { this._adapter.nuke(); }, remove: function (key) { this._adapter.removeInternal(key); } } ); WinJS.Namespace.define("DataSources", { IndexedDbDataSource: IndexedDbDataSource }); })(); Summary In this blog post, I provided an overview of how you can create a new data source which you can use with the WinJS library. I described how you can create an IndexedDbDataSource which you can use to bind a ListView control to an IndexedDB database. While describing how you can create a custom data source, I explained how you can implement the IListDataAdapter interface. You also learned how to raise notifications — such as a removed or invalidateAll notification — by taking advantage of the methods of the IListDataNotificationHandler interface.

    Read the article

< Previous Page | 231 232 233 234 235 236 237 238 239 240 241 242  | Next Page >